【问题标题】:Why does this assembly program produce no output?为什么这个汇编程序没有输出?
【发布时间】:2015-01-10 20:23:09
【问题描述】:

作为 x86_64 程序集的新手,我正在尝试在运行 64 位 OpenBSD 的笔记本电脑上编写一个基本的“hello”程序。该程序以退出代码 0 运行至完成,但似乎忽略了将文本写入标准输出的系统调用。为什么?

我正在使用 GNU 汇编器并使用以下命令创建可执行文件:

as -o hello.o hello.s; ld -Bstatic hello.o

# OpenBSD ELF identification
.section ".note.opensd.ident", "a"
.p2align 2
.long 0x8
.long 0x4
.long 0x1
.ascii "OpenBSD\0"
.long 0x0
.p2align 2

.section .data
msg: .ascii "hello"

.section .text
.globl _start
_start:
    push $5 # number of bytes to write
    push $msg # message address
    push $1 # file descriptor 1 for stdout
    mov $4, %eax # write is system call 4
    syscall

    push $0 # exit code 0
    mov $1, %eax # exit is system call 1
    syscall

【问题讨论】:

  • 我不知道 OpenBSD,但是在 Linux 上,如果你想使用 syscall,你应该在 rdi/rsi/rdx/r10/r8/r9 中传递参数,而不是使用堆。 It seems to be the same on FreeBSD。也许你混淆了 syscall 和 int 0x80 ?
  • 在寄存器中传递参数有效。显然,32 位 BSD 使用stack,而 64 位版本使用寄存器。如果您不介意,syscall 和 int 0x80 有什么区别?据我所知,int 0x80 仅表示中断 80,用于系统调用。

标签: assembly x86-64 openbsd


【解决方案1】:

由于您标记 x86_64 并且可能在 x86_64 系统上。因此,您需要:

  • 作为--64
  • 使用 pushq 而不是 pushl 将 64 位值压入堆栈
  • 在系统调用之前将这些值传输到适当的寄存器

    .section ".note.opensd.ident", "a"
    .p2align 2
    .long 0x8
    .long 0x4
    .long 0x1
    .ascii "OpenBSD\0"
    .long 0x0
    .p2align 2
    
    .section .data
     msg: .ascii "hello"
    
    .section .text
    .globl _start
    _start:
            pushq $0x4
            popq %rax               # 4 (write syscall) into rax
            pushq $0x1
            popq %rdi               # 1 (STDOUT) into rdi
            pushq $msg
            popq %rsi               # address of hello msg into rsi
            pushq $0x5
            popq %rdx               # length of hello msg into rdx
            syscall
            pushq $1
            popq %rax
            pushq $0
            popq %rdi
            syscall
    

以下文章提供了一些有用的信息:

x64 asm on FreeBSD

differences between x86 and x64 asm

【讨论】:

  • 接受工作代码,感谢您的文章。
  • push $4 / pop %rax 是写mov $4, %eax 的一种奇怪且低效的方式。如果您正在优化代码大小而不是速度,或者编写需要避免机器代码中的 00 字节的 shellcode,您通常只会做类似的事情。一旦你有了一个常量,如果你真的想优化代码大小而不是性能和可读性,你可以使用 3 字节指令 lea -3(%rax), %edilea 相对于它的其他常量。
猜你喜欢
  • 1970-01-01
  • 2021-12-06
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-05
  • 2023-04-09
相关资源
最近更新 更多