1

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
4

2 回答 2

6

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

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 日以来的秒数。)

为了避免将数字直接打印到 unix 控制台的复杂性,我将作弊并提供一个完整的示例,该示例在 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 位可执行文件,因为它使用 push 和 pop,并且您无法将 32 位寄存器压入 64 位堆栈。

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

那么你应该得到

$ ./systime
1310190574

我已经在 32 位和 64 位 linux 上对此进行了测试,并设法编译了上述代码。如果您有任何问题,请告诉我。

为了回答您关于 nasm 教程的问题,我最近一直在学习 Jeff Duntemann 的“Assembly Language Step By Step, Third Edition”。有关详细信息和示例章节,请参见http://www.duntemann.com/assembly.html

于 2011-07-09T17:13:19.860 回答
3

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

#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);
}
于 2009-08-07T01:59:43.360 回答