gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 03:47:06 27 4
gpt4 key购买 nike

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

最佳答案

EAX 保存 32 位,Intel 称之为“整数”。程序员(有时是汇编器)决定如何解释这些位。如果您使用数字 50(而不是字符串“50”)加载 EAX

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 程序员做出的。其他汇编器可能有不同的行为。

关于linux - Nasm 中处理器寄存器的二进制表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27802500/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com