Получаване на 32-битови регистри от 64-битов nasm код

Уча 64-битов nasm, сглобявам .nasm файла, който съдържа САМО 64-битови регистри, като правя следното

nasm -f elf64 HelloWorld.nasm -o HelloWorld.o

и го свържете, като направите следното

ld HelloWorld.o -o HelloWorld

програмата работи правилно и дори казва, че е 64-битов ELF, когато стартирам командата file, но когато използвам objdump или gdb за разглобяване на изпълнимия файл, регистрите, които поставям като 64-битови регистри в кода, се показват като 32- битови регистри при разглобяване. (пример: rax в източника се показва като eax при разглобяване)

Защо е това?

Това не се случва само на един компютър и е нов проблем, не се е случвало преди.

HelloWorld.nasm:

global _start

section .text

_start:
        mov rax, 1
        mov rdi, 1
        mov rsi, hello_world
        mov rdx, length
        syscall

        mov rax, 60
        mov rdi, 11
        syscall

section .data

        hello_world: db 'Hello World',0xa
        length: equ $-hello_world

Разглобен HelloWorld:

...
00000000004000b0 <_start>:
  4000b0:       b8 01 00 00 00          mov    eax,0x1
  4000b5:       bf 01 00 00 00          mov    edi,0x1
  4000ba:       48 be d8 00 60 00 00    movabs rsi,0x6000d8
  4000c1:       00 00 00
  4000c4:       ba 0c 00 00 00          mov    edx,0xc
  4000c9:       0f 05                   syscall
  4000cb:       b8 3c 00 00 00          mov    eax,0x3c
  4000d0:       bf 0b 00 00 00          mov    edi,0xb
  4000d5:       0f 05                   syscall
...

person themustang    schedule 22.10.2014    source източник
comment
Не всички регистри, само тези, където премествате стойности, които се вписват в 32 бита, вижте stackoverflow.com/questions/11177137/   -  person Andreas Fester    schedule 22.10.2014


Отговори (1)


Защо

...
mov rax, 1
mov rdi, 1
mov rsi, hello_world
...

се разглобява като

...
4000b0:       b8 01 00 00 00          mov    eax,0x1
4000b5:       bf 01 00 00 00          mov    edi,0x1
4000ba:       48 be d8 00 60 00 00    movabs rsi,0x6000d8
4000c1:       00 00 00
...

Тъй като литералът 0x1 се побира в 32 бита и горните 32 бита на 64-битов регистър са зададени на 0 при зареждане на долните 32 бита през съответния E-регистър. Следователно асемблерът може да оптимизира mov до 32-битова операция.

Имайте предвид, че адресът, зареден в rsi, може да не се побира в 32 бита, следователно rsi остава като такъв.

Ако добавите следните инструкции, можете да видите ефекта много ясно:

mov rbx, 0x0ffffffff      ; still fits into 32 bit
mov rbx, 0x100000000      ; does not fit into 32 bits anymore

се разглобява като

 a: bb ff ff ff ff          mov    $0xffffffff,%ebx
 f: 48 bb 00 00 00 00 01    movabs $0x100000000,%rbx
16: 00 00 00 

Можете да деактивирате оптимизирането на nasm с -O0, в който случай инструкциите запазват своя дълъг формат:

nasm -O0 -f elf64 HelloWorld.asm 

Резултат:

14: 48 bb ff ff ff ff 00    movabs $0xffffffff,%rbx
1b: 00 00 00 
1e: 48 bb 00 00 00 00 01    movabs $0x100000000,%rbx
25: 00 00 00 
person Andreas Fester    schedule 22.10.2014