【问题标题】:g++ dumped assembly output doesn't workg++ 转储的程序集输出不起作用
【发布时间】:2014-12-31 02:58:41
【问题描述】:

我在 main.cpp 文件中有以下 C++ 代码。

int add(int a,int b)
{
    int c = a + b;
    return c;
}


int main()
{
    int a = 2;
    int b = 4;
    int d = add(2,4);
}

当我运行 g++ -S main.cpp 时,我得到了以下汇编代码。(删除所有调试符号后)。我还更改了代码以使用 sys_write 系统调用打印两个数字的总和。

.text
.globl  _Z3addii
_Z3addii:
pushq   %rbp
movq    %rsp, %rbp
movl    %edi, -20(%rbp)
movl    %esi, -24(%rbp)
movl    -24(%rbp), %eax
movl    -20(%rbp), %edx
addl    %edx, %eax
movl    %eax, -4(%rbp)
movl    -4(%rbp), %eax
popq    %rbp
ret
.globl  main

main:
pushq   %rbp
movq    %rsp, %rbp
subq    $16, %rsp
movl    $2, -12(%rbp)
movl    $4, -8(%rbp)
movl    $4, %esi
movl    $2, %edi
call    _Z3addii
movl    %eax, -4(%rbp)

movl    $4, %edx            #message length
movl    -4(%rbp), %esi      #message to write
movl    $1, %edi            #file descriptor (stdout)
movl    $1, %eax            #system call number (sys_write)
syscall                     #call kernel

movl    $60, %eax           # Invoke the Linux 'exit' syscall
movl    $0, %edi            # With a return value of 0
syscall                     # call kernel
ret

我的问题是,当我运行上面的程序集时,它什么也没有输出。我不明白我在这里错过了什么?有人可以告诉我我错过了什么吗?谢谢。

使用的命令: g++ -o main main.s 和 ./main -->无输出

操作系统:Ubuntu 12.04 64bit 和 g++ 版本:4.8.2

【问题讨论】:

  • 它甚至调用add 有点令人惊讶,我敢打赌它只会在堆栈上写 6。或者根本不编译该路径。
  • 您没有执行任何printfcout,那么您为什么希望看到任何类型的输出?
  • @greatwolf 可能是因为他们正在执行sys_write 系统调用。查看修改后的汇编代码。

标签: c++ assembly system-calls instruction-set


【解决方案1】:

你做错了两件事:

首先,您是 64 位系统调用指令,但仅初始化寄存器的 %e 部分。其次,这个:

movl    -4(%rbp), %esi

sys_write 期望该值的内存地址时(我的意思是%rsi),将-4(%rbp)(您刚刚计算的6)处的值加载到%esi。它适用于:

movq    $1, %rax            #system call number (sys_write)
movq    $1, %rdi            #file descriptor (stdout)
leaq    -4(%rbp), %rsi      #message to write
movq    $4, %rdx            #message length
syscall                     #call kernel

当然,您不会以这种方式获得格式化输出。要查看 6 是否已打印,您必须通过 hexdump 或类似的方式传输输出。

附录:您只初始化寄存器的%e 部分实际上仅在%rsi 的情况下才真正关键。 %rbp 在读取时保存一个设置了高位的值,如果仅将-4(%ebp) 写入%esi,这些值就会丢失。从技术上讲,这也有效:

movl    $1, %eax            #system call number (sys_write)
movl    $1, %edi            #file descriptor (stdout)
leaq    -4(%rbp), %rsi      #message to write
movl    $4, %edx            #message length
syscall                     #call kernel

...但我觉得它的风格很差。

【讨论】:

  • 使用下面的命令通过 hexdump 管道输出。 -d 选项是转换为十进制。 ./主要 | hexdump -d output: 0000000 00006 0000004 这里4是写入的字节数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-24
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
相关资源
最近更新 更多