2015-07-12 3 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 

Hex дамп:

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 is ... ??? Что это?

0x1521 в десятичной форме, и я могу считать пальцем, отслеживающим шестнадцатеричный дамп, что сообщение «Hello world» составляет ровно 21 байт после инструкции LEA rsi, [msg]. Таким образом, это должен быть относительный адрес, но откуда приходит 10 00 00? Я бы понял, если это было 1500 00, но по какой-то причине 1500 00.

К сожалению, ссылки на ЦП не очень полезны, они настолько формальны, и я не могу с ними соглашаться. Они выглядят так:

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. Отсюда причина, по которой вы видите 15 10 00 00 в hexdump, так как это относительное смещение 0x00001015.

+0

означает, что весь двоичный файл 'hello' загружен во все (два) сегмента? Я имею в виду * целый * файл, а не только данные сегмента 'phoff-phoff + phsize'. – exebook

+0

Если вы имеете в виду, как он будет загружен ОС, то я не уверен. Я не рассматривал такие детали для исполняемых файлов ELF. – Michael

Смежные вопросы