LEA指令操作码生成

时间:2015-07-12 10:36:07

标签: assembly cpu opcode

这个问题关于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位前缀,8dLEA代码,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操作码,如果可能的话。

1 个答案:

答案 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