在Nasm的处理器寄存器中的二进制表示

时间:2015-01-06 16:07:59

标签: linux assembly binary x86 nasm

我想问一下将指令放入寄存器的过程。例如:我们想要覆盖计数' 50'进入EBX(在ASCII' 50'是计数' 2')。 EBX由32位组成。当我们把50'进入它,它将被安排为二进制代表,是吗? (0000000 | 00000000 | 00000000 | 00110010)。有权利吗?当我们将一个字符串放入寄存器时,位会发生什么?

1 个答案:

答案 0 :(得分:0)

EAX保留32位,英特尔称之为"整数"。程序员 - 有时是汇编程序 - 决定如何解释这些位。如果您使用数字50加载EAX(不是字符串' 50')

mov eax, 50

汇编程序决定生成一个机器指令,以一种方式加载50,你可以在二进制系统中将它读作数字50:

  

00000000000000000000000000110010

尝试一下,如果你用字符串喂它,汇编器会做什么:

GLOBAL _start

SECTION .bss
    outstr resb 40

SECTION .data
    _start:
        mov eax, 'Four'         ; Load EAX with a string
        call int2bin            ; Convert it to a binary string in outstr
        mov byte [edi], 10      ; Add a line feed
        inc edi                 ; Increment the pointer

        mov eax, 4              ; SYS_WRITE
        mov ebx, 1              ; STDOUT
        mov ecx, outstr         ; Pointer to output buffer
        mov edx, edi            ; Count of bytes to send:
        sub edx, outstr         ;   EDX = EDI (offset returned from int2bin) - offset of output buffer
        int 0x80                ; Call kernel

        mov eax, 1              ; SYS_EXIT
        xor ebx, ebx            ; Returncode: 0 (ok)
        int 0x80                ; Call kernel

    int2bin:    ; Converts an integer in EAX to a binary string in outstr
        mov edi, outstr         ; Pointer to a string
        mov ecx, 32             ; Loop counter

        .LL1:
        test cl, 0b111          ; CL%8 = 0 ?
        jnz .F                  ; No: skip the next instructions
        mov Byte [edi], ' '     ; Store a space
        inc edi                 ; and increment the pointer
        .F:

        shl eax, 1              ; The leftmost bit into carry flag
        setc dl                 ; Carry flag into DL
        or dl, '0'              ; Convert it to ASCII
        mov [edi], dl           ; Store it to outstr
        inc edi                 ; Increment the pointer
        loop .LL1               ; Loop ECX times

        mov byte [edi], 0       ; Null termination if needed as C string (not needed here)
        ret

输出:

  

01110010 01110101 01101111 01000110

NASM在EAX中将向后存储起来。最左边的字符的ASCII存储在EAX的最右边的字节中,倒数第二个字符在第二个字节中找到,依此类推。最好查看这些字节何时打印为ASCII字符:

GLOBAL _start

SECTION .bss
    outstr resb 40

SECTION .data
    _start:
        mov eax, 'Four'         ; Load EAX with a string
        call int2str            ; Convert it to a binary string in outstr
        mov byte [edi], 10      ; Add a line feed
        inc edi                 ; Increment the pointer

        mov eax, 4              ; SYS_WRITE
        mov ebx, 1              ; STDOUT
        mov ecx, outstr         ; Pointer to output buffer
        mov edx, edi            ; Count of bytes to send:
        sub edx, outstr         ;   EDX = EDI (offset returned from int2bin) - offset of output buffer
        int 0x80                ; Call kernel

        mov eax, 1              ; SYS_EXIT
        xor ebx, ebx            ; Returncode: 0 (ok)
        int 0x80                ; Call kernel

    int2str:    ; Converts an integer in EAX to an ASCII string in outstr
        mov edi, outstr         ; Pointer to a string
        mov ecx, 4              ; Loop counter

        .LL1:
        rol eax, 8
        mov [edi], al           ; Store it to outstr
        inc edi                 ; Increment the pointer
        loop .LL1               ; Loop ECX times

        mov byte [edi], 0       ; Null termination if needed as C string (not needed here)
        ret

输出:

  

ruoF

上述两个程序都以大端序显示EAX。这是您熟悉查看十进制数的顺序。最重要的数字是左边,最低有效数字是正确的。但是,EAX将保存在little endian order的内存或磁盘中,从右侧开始具有最低有效字节的序列。使用反汇编程序或调试程序查看内存,您会看到' F' o',' u'' r'以及您使用.datadb 'Four'部分中对其进行了定义。因此,当您使用字符串加载寄存器,将其保存到内存并调用内核的写例程时,您将没有任何区别:

GLOBAL _start

SECTION .bss
    outstr resb 40

SECTION .data
    _start:
        mov eax, 'Hell'             ; Load EAX with the first part of the string
        mov ebx, 'o wo'             ; Load EBX with the second part
        mov ecx, 'rld!'             ; Load ECX with the third part
        mov dword [outstr], eax     ; Store the first part in outstr (little endian)
        mov dword [outstr+4], ebx   ; Append the second part
        mov dword [outstr+8], ecx   ; Append the third part

        mov eax, 4                  ; SYS_WRITE
        mov ebx, 1                  ; STDOUT
        mov ecx, outstr             ; Pointer to output buffer
        mov edx, (3*4)              ; Count of bytes to send (3 DWORD à 4 bytes)
        int 0x80                    ; Call kernel

        mov eax, 1                  ; SYS_EXIT
        xor ebx, ebx                ; Returncode: 0 (ok)
        int 0x80                    ; Call kernel

输出:

  

Hello world!

请注意:此行为是由NASM程序员完成的。其他汇编程序可能有不同的行为。