我想问一下将指令放入寄存器的过程。例如:我们想要覆盖计数' 50'进入EBX(在ASCII' 50'是计数' 2')。 EBX由32位组成。当我们把50'进入它,它将被安排为二进制代表,是吗? (0000000 | 00000000 | 00000000 | 00110010)。有权利吗?当我们将一个字符串放入寄存器时,位会发生什么?
答案 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'以及您使用.data
在db '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程序员完成的。其他汇编程序可能有不同的行为。