linux 32 64 汇编查看,linux – 32位模式下的NASM x86_64汇编:为什么该指令会生成RIP相对寻址代码?...

[bits 32]

global _start

section .data

str_hello db "HelloWorld", 0xa

str_hello_length db $-str_hello

section .text

_start:

mov ebx, 1 ; stdout file descriptor

mov ecx, str_hello ; pointer to string of characters that will be displayed

mov edx, [str_hello_length] ; count outputs Relative addressing

mov eax, 4 ; sys_write

int 0x80 ; linux kernel system call

mov ebx, 0 ; exit status zero

mov eax, 1 ; sys_exit

int 0x80 ; linux kernel system call

这里的基本要点是我需要将hello字符串的长度传递给linux的sys_write系统调用.现在,我很清楚我可以使用EQU,它会工作正常,但我真的想了解这里发生了什么.

所以,基本上当我使用EQU时,它会加载值,这很好.

str_hello_length equ $-str_hello

...

...

mov edx, str_hello_length

但是,如果我将此行与DB一起使用

str_hello_length db $-str_hello

...

...

mov edx, [str_hello_length] ; of course, without the brackets it'll load the address, which I don't want. I want the value stored at that address

而不是像我期望的那样在该地址加载值,汇编器输出RIP相对寻址,如gdb调试器中所示,我只是想知道为什么.

mov 0x6000e5(%rip),%edx # 0xa001a5

现在,我尝试使用eax寄存器(然后将eax移动到edx),但后来我遇到了另一个问题.我最终得到了一个分段错误,如gdb中所述:

movabs 0x4b8c2890[bits 32]

global _start

section .data

str_hello db "HelloWorld", 0xa

str_hello_length db $-str_hello

section .text

_start:

mov ebx, 1 ; stdout file descriptor

mov ecx, str_hello ; pointer to string of characters that will be displayed

mov edx, [str_hello_length] ; count outputs Relative addressing

mov eax, 4 ; sys_write

int 0x80 ; linux kernel system call

mov ebx, 0 ; exit status zero

mov eax, 1 ; sys_exit

int 0x80 ; linux kernel system call

e5,%eax

显然,不同的寄存器产生不同的代码.我想我需要以某种方式截断高32位,但我不知道该怎么做.

虽然有点找到了“解决方案”,但它是这样的:

用str_hello_length的地址加载eax,然后加载eax指向的地址的内容,一切都是hunky dory.

mov eax, str_hello_length

mov edx, [eax] ; count

; gdb disassembly

mov $0x6000e5,%eax

mov (%rax),%edx

显然试图从mem地址间接加载一个值产生不同的代码?我真的不知道.

我只需要帮助理解这些指令的语法和操作,这样我就可以更好地理解为什么如何加载有效地址.是的,我想我可以切换到EQU并以我的快乐方式,但我真的觉得我不能继续,直到我理解DB声明发生了什么并从它的地址加载.

解决方法:

答案是不是. x86-64在32位仿真模式下没有RIP相对寻址(这应该是显而易见的,因为RIP不存在于32位中).正在发生的事情是,nasm正在编译一些你试图以64位运行的可爱的32位操作码. GDB将您的32位操作码拆分为64位,并告诉您在64位中,这些字节意味着RIP相对的mov. x86-64上的64位和32位操作码与硅片中的常见解码逻辑重叠很多,你会感到困惑,因为GDB反汇编的代码看起来类似于你写的32位代码,但实际上你只是在处理器上扔垃圾字节.

这与nasm没有任何关系.您正在使用错误的体系结构进行处理.要么在32位进程中使用32位nasm,要么为[BITS 64]编译汇编代码.

标签:linux,assembly,x86-64,nasm,relative

来源: https://codeday.me/bug/20190729/1573828.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值