Nasm中处理器寄存器中的二进制表示 [英] Binary representation in processor's registers in Nasm

查看:130
本文介绍了Nasm中处理器寄存器中的二进制表示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想问一下将指令放入寄存器的过程.例如:我们想将计数'50'覆盖到EBX中(ASCII'50'是计数'2'). EBX由32位组成.当我们将"50"放入其中时,它会以二进制表示的形式排列,是吗? (0000000 | 00000000 | 00000000 | 00110010).有权利吗当我们将一个字符串放入寄存器时,位会发生什么?

I would like to ask about process of put instructions into registers. For example: we want to overwrite count '50' into EBX (in ASCII '50' is count '2'). EBX consists of 32 bits. When we put '50' into it, it will be arranged as binary represent, yes? (0000000 | 00000000 | 00000000 | 00110010). Have a right? What happens with bits, when we place a string into register?

推荐答案

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

EAX holds 32 bits which Intel calls "integer". The programmer - and sometimes the assembler - decides how to interpret these bits. If you load EAX with the number 50 (not the string '50')

mov eax, 50

汇编程序决定生成一条机器指令,该指令以某种方式加载50,您可以在二进制系统中将其读取为数字50:

the assembler decides to generate a machine instruction that loads the 50 in a manner, that you can read it as number 50 in a binary system:

00000000000000000000000000110010

00000000000000000000000000110010

尝试一下,如果您使用字符串来输入汇编器,它将执行以下操作:

Try out, what the assembler does if you feed it with a string:

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

01110010 01110101 01101111 01000110

NASM 向后将其存储在EAX中.最左侧字符的ASCII存储在EAX的最右侧字节中,倒数第二个字符位于第二个字节中,依此类推.最好看看这些字节何时以ASCII字符打印:

NASM stored it backwards in EAX. The ASCII of leftmost character is stored in the rightmost byte of EAX, the second-to-last character is to be found in the second byte, and so on. Better to see when those bytes are printed as ASCII characters:

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

ruoF

以上两个程序均按大端顺序显示EAX.这是您熟悉的十进制数字顺序.最高有效数字在左边,最低有效数字在右边.但是,EAX将按照 小端序 ,从右侧开始以最低有效字节开始.使用反汇编器或调试器查看内存,您将看到'F','o','u','r'以及您在.data部分的db 'Four'中定义的内容.因此,当您使用字符串加载寄存器,将其保存到内存并调用内核的写入例程时,您不会有任何区别:

Both programs above show EAX in big endian order. This is the order you are familiar with looking at decimal numbers. The most significant digit is left and the least significant digit is right. However, EAX would be saved in memory or disk in little endian order, starting the sequence from the right with the least significant byte. Looking at the memory with a disassembler or debugger you would see 'F','o','u','r' as well as you had defined it in a .data section with db 'Four'. Therefore you'll get no difference when you load a register with a string, save it to memory and call the write routine of the kernel:

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程序员进行的.其他汇编程序可能会有不同的行为.

Please note: This behavior is made by the NASM programmers. Other assemblers might have a different behavior.

这篇关于Nasm中处理器寄存器中的二进制表示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆