我们大多数人接触汇编都是在windows平台中,基于Masm开发80x86汇编语言。但是现在CPU都是64位,寻址空间也不再是以前的2^20的1MB寻址范围,而是2^64的超大寻址范围。当时之所会引出段地址和偏移地址的概念,我个人认为主要原因是寄存器的位数与地址总线位数不一致,所以才需要 段地址x16+偏移地址的形式。现在的64位CPU寄存器是64位,地址总线也是64位,因此寻址可以使用绝对内存地址的形式。
这张图片是64位CPU的结构,因此在开发64寻址模式的汇编语言时,需要采用64位寻址。
在Mac中开发64位汇编程序需要使用到Nasm,这个是本人基于Nasm开发的一个64位调试程序,可以打印数据到控制台中。
SECTION .data
gupMsg: resb 100 ;显示内存区域
gupMsgLen: equ $-gupMsg ;显示区域大小
gupMsgIndex: dd 0x0,0x0 ;记录显示的当前内存位置
tmpMsg1: dd 0x0,0x0,0x0,0x0; 临时内存区域
tmpMsg2: dd 0x0,0x0,0x0,0x0; 临时内存区域
SECTION .text
global _main
;将数字转化为Acsii编码
;输入rax,输出rax,rdx
LongToChar:
push rbx
push rbp
push rsi
push rcx
mov rbx,tmpMsg1
mov [rbx],rax
mov rbp,tmpMsg2
add rbp,15
mov rsi,0
mov cx,8
Ls: mov al,[rbx+rsi]
mov ah,al
and al,00001111b
add al,0x30
cmp al,0x39
jna o1
add al,0x7
o1: shr ah,0x4
and ah,00001111b
add ah,0x30
cmp ah,0x39
jna o2
add ah,0x7
o2: mov byte [rbp],al
dec rbp
mov byte [rbp],ah
dec rbp
inc rsi
loop Ls
mov rbp,tmpMsg2
mov rax,[rbp]
mov rdx,[rbp+8]
pop rcx
pop rsi
pop rbp
pop rbx
ret
;打印rax中内容,调试tag存放在r8中
LogLong:
push rax
push rdi
push rsi
push rdx
push rbx
push r9
call LongToChar
mov rbx,gupMsg
mov rbp,gupMsgIndex
mov rdi,[rbp]
mov r9,0x0
;增添tag
mov [rbx+rdi],r8
add rdi,8
add r9,8
mov byte [rbx+rdi],','
inc rdi
inc r9
;增添寄存器说明
mov dword [rbx+rdi],'rax='
add rdi,4
add r9,4
mov word [rbx+rdi],'0x'
add rdi,2
add r9,2
;增添真实内容
mov [rbx+rdi],rax
add rdi,8
add r9,8
mov [rbx+rdi],rdx
add rdi,8
add r9,8
mov byte [rbx+rdi],0x0a
inc rdi
inc r9
mov [rbp],rdi
;传递数据到显存
mov rax,0x2000004
mov rdi,1
mov rsi,gupMsg
add rsi,[rbp]
sub rsi,r9
mov rdx,r9
syscall
pop r9
pop rbx
pop rdx
pop rsi
pop rdi
pop rax
ret
kernel:
syscall
ret
_main:
;核心代码执行
mov r8,'test1' ;调试内容标题
mov rax,0x11111 ;需要打印的调试内容
call LogLong
mov r8,'test2'
mov rax,rbx
call LogLong
mov rax,0x2000001
mov rdi,0
call kernel
使用nasm进行编译
/etc/nasm-2.12/nasm -f macho64 printf.nasm
需要使用新版本的nasm,本人放到的/etc/nasm-2.12/目录下,原代码放到了printf.nasm中。下载最新版本的nasm可以到www.nasm.us下载。
之后再链接
ld -o printf -e _main printf.o
也可以将两个命令放到一起
/etc/nasm-2.12/nasm -f macho64 printf.nasm;ld -o printf -e _main printf.o
./printf查看运行结果