2015-07-12 72 views
0

这个问题是不是关于LEA指令,不是关于它是如何工作的,它不是重复的。这是关于OPCODE代这个指令。LEA指令操作码生成

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是... ???它是什么?

0x1521的十进制数,我可以用一个手指跟踪十六进制转储,即“Hello world”消息正好是LEA rsi, [msg]指令后的21个字节。所以它必须是一个相对地址,但10 00 00来自哪里?我会理解,如果它是1500 00,但由于某种原因它是1500 00

不幸的是,CPU引用并不是非常有用,它们非常正式,我无法与它们相处。他们是这样的:

8D r LEA Gvqp M gen datamov Load Effective Address 

所以,请解释LEA操作码是如何在这种情况下产生的,如果可能的话一般英寸

回答

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

+0

这是否意味着整个二进制文件'hello'被加载到所有(两个)段中?我的意思是*整个*文件,而不仅仅是段的数据'phoff-phoff + phsize'。 – exebook

+0

如果你的意思是它将如何被操作系统加载,那么我不确定。我还没有处理ELF可执行文件的这些细节。 – Michael