Assembly Endianness-何时订购?
我得到了endianness的一般概念,但我对endianness如何以及何时出现的机制有点模糊。我有一个英特尔x64的组装示例:Assembly Endianness-何时订购?,assembly,endianness,Assembly,Endianness,我得到了endianness的一般概念,但我对endianness如何以及何时出现的机制有点模糊。我有一个英特尔x64的组装示例: section .data newline_char: db 10 codes: db '0123456789abcdef' section .text global _start print_newline: mov rax, 1 ; 'write' syscall identifier mov rdi, 1
section .data
newline_char: db 10
codes: db '0123456789abcdef'
section .text
global _start
print_newline:
mov rax, 1 ; 'write' syscall identifier
mov rdi, 1 ; 'stdout' file descriptor
mov rsi, newline_char ; starting address of data
mov rdx, 1 ; number of bytes to write
syscall
ret
print_hex:
mov rax, rdi ; move input (rdi) to rax
mov rdi, 1 ; 'stdout' file descriptor
mov rdx, 1 ; number of bytes to write
mov rcx, 64 ; bit/position counter
iterate:
push rax ; save input, rax altered later
sub rcx, 4 ; every iteration shifts 4 fewer
sar rax, cl ; shift rax 'cl' times (cl is lowest byte of rcx)
and rax, 0xf ; 'AND' rax with 0xf to preserve lowest 4 bits
lea rsi, [codes + rax] ; add value of rax to address of codes
mov rax, 1 ; 'write' syscall identifier (prepare to write)
push rcx ; 'write' syscall alters rcx (counter) (rcx caller saved)
syscall
pop rcx ; restore counter
pop rax ; restore original input
test rcx, rcx ; rcx & rcx -> (set flags)
jnz iterate ; if not zero, load 'iterate' to RIP
ret
section .data
demo1: dq 0x1122334455667788
demo2: db 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80
section .text
_start:
mov rdi, [demo1]
call print_hex
call print_newline
mov rdi, [demo2]
call print_hex
call print_newline
mov rax, 60
xor rdi, rdi
syscall
当我按原样运行时,我得到1122334455667788
和80706050430010
所以,在这一点上我有点困惑,因为我认为88
和80
都会存储在第一个内存地址中
在这一点上,我认为如果我保持标记值不变,并将64位rax
寄存器更改为32位eax
寄存器,我将得到11223344
和80706050
。但是,我得到了11223344
和40302010
如果我仍然在demo2
中使用db
存储相同的8个字节,我应该先获得相同的最低有效字节吗
还有,为什么
demo1
不按相反的顺序打印?endianness是否只适用于单个存储的字节?您使用的汇编程序也知道您的处理器是little endian。因此,当您使用dq
时,它知道88是小头,应该首先存储。当您使用db
时,它不再有用,现在字节顺序很重要,10是小的结束。当您使用eax而不是rax时,寄存器不再能够表示大端的四个字节,它们就消失了。没有发生任何特殊情况。因此,如果dq
在小端存储88
,为什么从该内存地址开始打印不会产生88776655
?因为您的代码专门以大端打印?你从最重要的半字节开始。你的打印十六进制代码没有被破坏,它知道需要先打印大头。因此,SAR在循环中第一次移动60位。Endity在该代码中不起任何作用。如果您将其更改为eax
,您应该获得demo155667788
,而不是11223344
???(由于demo1
处的内存内容是8877665544332211
,而demo2
处的内存内容是102030050607080
(从汇编程序中检查列表文件,并将其加载到调试器中,在获取后检查内存视图与rax/eax
的内容)。(不要依赖于print
进行调试,只要找到适合您的好调试器(gdb
或edb调试器
是两个完全不同的选项,其中一个应该适合您)。