汇编代码寄存器和相关值的重新分配

时间:2017-03-14 15:00:10

标签: assembly

问题:

我的理解是寄存器EAX,EBX,ECX,EDX是"通用"根据{{​​3}}或多或少可互换。link。那么为什么当我在下面的代码中交换操作数/值时,它不再打印"Hello World!"

测试

切换mov后面的寄存器edxecx下面的值/操作数。

mov edx,13
mov ecx,msg

mov edx,msg
mov ecx,13

结果:

打破代码。我显然误解了它是如何工作的,所以会赞赏一些指导。最终,我试图更好地理解为什么以及如何使用某些寄存器。

代码示例:

取自here的原始工作代码:

section .text
    global _start   ;must be declared for linker (ld)
_start:             ;tells linker entry point
    mov edx,13      ;message length
    mov ecx,msg     ;message to write
    mov ebx,1       ;file descriptor (stdout)
    mov eax,4     ;system call number (sys_write)
    int 0x80        ;call kernel

    mov eax,1       ;system call number (sys_exit)
    int 0x80        ;call kernel

section .data
msg db 'Hello, world!', 0xa  ;string to be printed
len equ $ - msg     ;length of the string

2 个答案:

答案 0 :(得分:2)

寄存器可以平等使用,但它们不一定具有相同的含义。系统调用每个为它们分配不同的含义:

  • int 0x80要求eax用于确定您正在调用的系统调用。
  • sys_writeeax为4)要求ebx持有文件描述符,ecx保留字符缓冲区,edx保持长度。

如果你交换这些值,你肯定会得到正确的结果,因为它与将错误位置的值传递给函数的情况相同;它不会得到它所期望的。

在您自己的代码中,您可以随意使用它们(这就是“可互换”在该介绍页面上的真正含义),但是当您调用其他代码时,您必须遵循其他代码可能设置的任何规则。

答案 1 :(得分:2)

程序中断了,因为这些寄存器是可以互换的:它们的含义是写入它们的代码部分与从中读取的部分之间的协议。

在您的情况下,int 0x80控制内核进程,该进程希望从这些寄存器中读取某些值。正如对原始代码的评论所说,它希望阅读:

  • 来自eax的系统电话号码(4 = sys_write)
  • 来自ebx(1 = stdout)
  • 的文件描述符
  • 指向ecx
  • 字符串开头的指针
  • 来自edx
  • 的字符串的长度

如果您交换周围的值,它无法知道您已经这样做了;所以它从ecx读取值13,并假设你的字符串开始的地方,然后从edx读取一个内存地址,并假设你的字符串长度。

就高级语言而言,就像你改变了这一点:

sys_call(sys_write, stdout, msg_address, 13);

到此:

sys_call(sys_write, stdout, 13, msg_address);