这个问题不关于LEA指令,而不是关于它是如何工作的,它不是重复的。这是关于此指令的 OPCODE生成。
LEA操作码中的操作数是多少?
这是我的"你好world.fasm":
汇编程序:
format ELF64 executable at 0000000100000000h ; put image over 32-bit limit
segment readable executable
entry $
mov edx,msg_size ; CPU zero extends 32-bit operation to 64-bit
; we can use less bytes than in case mov rdx,...
lea rsi,[msg]
mov edi,1 ; STDOUT
mov eax,1 ; sys_write
syscall
xor edi,edi ; exit code 0
mov eax,60 ; sys_exit
syscall
segment readable writeable
msg db 'Hello 64-bit world!',0xA
msg_size = $-msg
十六进制转储:
000000b0 ba 14 00 00 00 48 8d 35 15 10 00 00 bf 01 00 00 |.....H.5........|
000000c0 00 b8 01 00 00 00 0f 05 31 ff b8 3c 00 00 00 0f |........1..<....|
000000d0 05 48 65 6c 6c 6f 20 36 34 2d 62 69 74 20 77 6f |.Hello 64-bit wo|
000000e0 72 6c 64 21 0a |rld!.|
000000e5
如您所见,感兴趣的指令lea rsi, [msg]
具有操作码48 8d 35 15 10 00 00
。从CPU指令引用我可以看出48
是排序的64位前缀,8d
是LEA
代码,35
是目标寄存器rsi
参考,15 10 00 00
是...... ???它是什么?
0x15
是十进制的21
,我可以用手指跟踪十六进制转储&#34; Hello world&#34;消息正好是LEA rsi, [msg]
指令后的21个字节。所以它必须是一个相对地址,但10 00 00
来自何处?我会理解它是15
00 00 00
,但由于某种原因,它是15
01 00 00
。
不幸的是,CPU引用不是很有用,它们是如此正式,我无法与它们达成协议。它们看起来像这样:
8D r LEA Gvqp M gen datamov Load Effective Address
因此,请解释在这种情况下如何生成LEA
操作码,如果可能的话。
答案 0 :(得分:3)
我将回答您关于15 10 00 00
是什么的问题,而不是关于LEA
如何编码的其他问题。
让我们通过readelf
获取有关可执行文件的一些信息:
$ readelf -l leatest Program headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x00000000000000b0 0x00000001000000b0 0x00000001000000b0 0x0000000000000021 0x0000000000000021 R E 1000 LOAD 0x00000000000000d1 0x00000001000010d1 0x00000001000010d1 0x0000000000000014 0x0000000000000014 RW 1000
然后让我们用ndisasm
(来自NASM)反汇编二进制文件:
ndisasm -b 64 leatest
000000B0 BA14000000 mov edx,0x14
000000B5 488D3515100000 lea rsi,[rel 0x10d1]
000000BC BF01000000 mov edi,0x1
000000C1 B801000000 mov eax,0x1
000000C6 0F05 loadall286
000000C8 31FF xor edi,edi
000000CA B83C000000 mov eax,0x3c
000000CF 0F05 loadall286
000000D1 48 rex.w ; <-- The string starts here
000000D2 656C gs insb
000000D4 6C insb
000000D5 6F outsd
000000D6 2036 and [rsi],dh
000000D8 342D xor al,0x2d
000000DA 62 db 0x62
000000DB 697420776F726C64 imul esi,[rax+0x77],dword 0x646c726f
000000E3 210A and [rdx],ecx
所以你的第二段 - 字符串所在的位置 - 的虚拟地址为0x00000001000010d1
,而代码则从虚拟地址0x00000001000000b0
开始。这些段在4096字节边界(0x1000)上对齐,因此字符串位于0x10D1 - 0xBC
相对于使用is的指令,等于0x1015
。因此,您在hexdump中看到15 10 00 00
的原因是因为它是相对偏移0x00001015
。