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

kyl*_*ylc 1 assembly nasm

我刚刚开始使用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
Run Code Online (Sandbox Code Playgroud)

jpo*_*ell 6

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

sys_time是系统调用13,所以

mov eax,13
Run Code Online (Sandbox Code Playgroud)

很好

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

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

push eax
Run Code Online (Sandbox Code Playgroud)

然后将堆栈指针输入ebx

mov ebx, esp
Run Code Online (Sandbox Code Playgroud)

现在进行系统调用

int 80h
Run Code Online (Sandbox Code Playgroud)

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

pop eax
Run Code Online (Sandbox Code Playgroud)

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

为了避免将数字直接打印到unix控制台的棘手问题,我将作弊并提供一个完整的示例,通过gcc编译nasm并与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
Run Code Online (Sandbox Code Playgroud)

编译

nasm -f elf sys_time.asm
gcc sys-time.o -o sys-time
Run Code Online (Sandbox Code Playgroud)

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

nasm -f elf32 sys_time.asm
gcc -m32 sys-time.o -o sys-time
Run Code Online (Sandbox Code Playgroud)

那你应该得到

$ ./systime
1310190574
Run Code Online (Sandbox Code Playgroud)

我已经在32位和64位linux上测试了这个并设法得到上面编译的代码.如果您有任何问题,请告诉我.

为了回答您关于nasm教程的问题,我最近从Jeff Duntemann的"汇编语言一步一步,第三版"中学习.有关详细信息和示例章节,请访问http://www.duntemann.com/assembly.html.