【问题标题】:NASM printing out time - code doesn't output anythingNASM 打印时间 - 代码不输出任何内容
【发布时间】:2009-08-06 23:18:12
【问题描述】:

我刚刚开始使用 ASM (NASM),需要一些关于以下 sn-p 的帮助。我没有收到任何错误/警告,它只是不输出任何内容。我期待的是它得到时间(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

【问题讨论】:

  • 不要自责。所有的组装都很糟糕。 ;)
  • 值得一提的是您正在使用哪个平台。
  • 我正在使用 NASM 开发 64 位 Linux。
  • @kyl,我想您正在组装 32 位二进制文​​件,对吧?因为在 64 位 Linux 中,您必须使用 64 位 asm,这与您发布的内容完全不同。

标签: assembly nasm


【解决方案1】:

这里的第一个问题是您需要了解 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

【讨论】:

  • sys_write 采用 ECX 中的指针,而不是 EBX。你想要push ...mov ecx, esp ; int 0x80 将推送的字节写入标准输出。
【解决方案2】:

这是您翻译成 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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-02
    • 1970-01-01
    • 2020-07-23
    • 2019-05-26
    • 2021-02-13
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    相关资源
    最近更新 更多