NASM 打印时间 - 代码不输出任何内容

发布于 2024-07-30 07:27:10 字数 396 浏览 1 评论 0原文

我刚刚开始使用 ASM (NASM),需要一些有关以下代码片段的帮助。 我没有收到任何错误/警告,它只是不输出任何内容。 我期望的是它获取时间 (13),然后打印出来 (4),然后退出 (1)。 另外,有人知道一些好的(最好是 NASM 特定的)ASM 教程吗?

section .bss
  time:   resb   255

section .text
  global _start

_start:
  mov   eax, 13
  int   0x80
  mov   eax, time

  mov   edx, 255
  mov   ecx, time
  mov   ebx, 1
  mov   eax, 4
  int   0x80

  mov   eax, 1
  int   0x80

I'm just getting started with ASM (NASM), and need some help with the following snippet. I get no errors/warnings, it just doesn't output anything. What I was expecting was for it to get the time (13), then print that out (4), then exit (1). Also, does anyone know of some good (preferably NASM specific) ASM tutorials?

section .bss
  time:   resb   255

section .text
  global _start

_start:
  mov   eax, 13
  int   0x80
  mov   eax, time

  mov   edx, 255
  mov   ecx, time
  mov   ebx, 1
  mov   eax, 4
  int   0x80

  mov   eax, 1
  int   0x80

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

﹂绝世的画 2024-08-06 07:27:10

这里的第一个问题是您需要了解 sys_time 系统调用。 http://syscalls.kernelgrok.com/ 上有一个方便的图表,可以告诉您各种系统的调用内容需要作为寄存器的输入。

sys_time 是系统调用 13,所以

mov eax,13

很好

,但是 sys_time 还需要在 ebx 中传递一个内存地址,在其中写入实际时间。

一种快速的方法是在堆栈上分配一些空间(我们可以将任何内容压入堆栈,sys_time 值将覆盖它,为什么不将 eax 的值粘贴到上面)。

push eax

然后将堆栈指针输入 ebx

mov ebx, esp

现在进行系统调用

int 80h

现在我们可以将时间从堆栈中弹出(例如 eax)

pop eax

现在 eax 包含当前的 unix 时间(即自 1970 年 1 月 1 日以来的秒数。)

避免打印的棘手问题我将作弊并提供一个完整的示例,该示例在 nasm 中编译并通过 gcc 与 c 库链接,并使用 printf

[SECTION .data]
PrintNum    db "%d",10,0 ;this is a c string so is null terminated
[SECTION .text]
extern printf       
global main

main:
        push ebp
    mov ebp,esp
    push ebx
    push esi
    push edi        ; stuff before this for glibc compatibility

    mov eax, 13
    push eax
    mov ebx, esp
    int 0x80
    pop eax

    push eax        ; push eax onto stack then the format string, then call printf to write eax to console, unwind stack pointer
    push PrintNum
    call printf 
    add esp,8   


    pop edi         ; stuff after this for glibc compatibility
    pop esi
    pop ebx
    mov esp,ebp
    pop ebp
    ret

编译

nasm -f elf sys_time.asm
gcc sys-time.o -o sys-time

虽然如果您使用的是 64 位 Linux,您可能必须这样做(并且有相关的multilib gcc 和 glibc)。 您无法将此程序编译为本机 64 位可执行文件,因为它使用压入和弹出,并且您无法将 32 位寄存器压入 64 位堆栈。

nasm -f elf32 sys_time.asm
gcc -m32 sys-time.o -o sys-time

然后你应该得到

$ ./systime
1310190574

我已经在 32 位和 64 位 Linux 上测试了这个并成功编译了上面的代码。 如果您有任何问题,请告诉我。

为了回答你关于nasm教程的问题,我最近一直在学习Jeff Duntemann的“汇编语言一步一步,第三版”。 有关详细信息和示例章节,请参阅 http://www.duntemann.com/ assembly.html

The first problem here is that you need to understand the sys_time sys call. There is a handy chart at http://syscalls.kernelgrok.com/ that tells you what the various sys calls require as input in registers.

sys_time is system call 13, so

mov eax,13

is good

However sys_time also requires a memory address to be passed in ebx, where it writes the actual time.

A quick way would be to allocate some space on the stack (we can push anything on the stack, the sys_time value will overwrite it, why not stick the value of eax onto it).

push eax

Then feed the stack pointer into ebx

mov ebx, esp

Now make the system call

int 80h

Now we can pop the time off the stack (into e.g. eax)

pop eax

Now eax contains the current unix time (i.e. number of seconds since Jan 01 1970.)

To avoid the trickyness of printing numbers directly to the unix console I will cheat and provide a complete example that compiles in nasm and links with the c library via gcc and uses printf

[SECTION .data]
PrintNum    db "%d",10,0 ;this is a c string so is null terminated
[SECTION .text]
extern printf       
global main

main:
        push ebp
    mov ebp,esp
    push ebx
    push esi
    push edi        ; stuff before this for glibc compatibility

    mov eax, 13
    push eax
    mov ebx, esp
    int 0x80
    pop eax

    push eax        ; push eax onto stack then the format string, then call printf to write eax to console, unwind stack pointer
    push PrintNum
    call printf 
    add esp,8   


    pop edi         ; stuff after this for glibc compatibility
    pop esi
    pop ebx
    mov esp,ebp
    pop ebp
    ret

Compile with

nasm -f elf sys_time.asm
gcc sys-time.o -o sys-time

Though if you are on 64-bit linux you might have to do (and have the relevant multilib gcc and glibc). You can't compile this program as a native 64-bit executable because it uses push and pop and you can't push a 32 bit register onto a 64 bit stack.

nasm -f elf32 sys_time.asm
gcc -m32 sys-time.o -o sys-time

Then you should get

$ ./systime
1310190574

I've tested this on 32 bit and 64 bit linux and managed to get the above code compiled. Let me know if you have any problems.

To answer your question regarded nasm tutorials, I have been learning recently from "Assembly Language Step By Step, Third Edition" by Jeff Duntemann. See http://www.duntemann.com/assembly.html for details and sample chapters.

锦上情书 2024-08-06 07:27:10

这是翻译为 C 的示例。您正在将指向时间的指针复制到 eax 而不是 eax 到缓冲区。 但这仍然行不通,因为您需要一个用于写入的字符数组,而不是一个会打印垃圾的原始整数。

#include <stdlib.h>

char b[255];

int
main()
{
        /* You wanted to do this which doesn't work
         * because write wont take int* but char arrays
         * *(int*)b=time(NULL);
         */

        /* Instead you did */
        time(NULL);
        b;
        write(1, b, 255);
        exit(1);
}

This is your example translated to C. You are copying the pointer to time to eax instead of eax to the buffer. Still that wouldn't work because you want a char array for write and not a raw integer which will print garbage.

#include <stdlib.h>

char b[255];

int
main()
{
        /* You wanted to do this which doesn't work
         * because write wont take int* but char arrays
         * *(int*)b=time(NULL);
         */

        /* Instead you did */
        time(NULL);
        b;
        write(1, b, 255);
        exit(1);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文