我正在按照Jack Crenshaw令人惊叹的编译器教程(翻译成c ++)创建我自己的玩具编程语言SP4RX。我正在构建一个64位的Ubuntu系统,因此我正在学习编译器的汇编。我正在制作一个加法程序作为开始:但我得到了一个分段错误并且核心被转储:(
section .text
global _start
_start:
mov rax, 0
add rax, [num1B]
add rax, [num2B]
mov [result], rax
mov rdx, [result]
mov rcx, 8
mov rax, 4
mov rbx, 1
int 80h
mov rbx, 1
mov rax, 0
int 80h
section .data
num1B: db 0Ah
num2B: db 0Ah
result: db 0
section .bss
关于我做错了什么建议?
答案 0 :(得分:3)
此程序不会添加两个字节,而是两个四字,因为您使用64位寄存器进行加载/存储。其中一个是从错位的地址读取的,因此是段错误。
num1B
,num2B
和result
应定义为dq
,而不是db
。
section .data
num1B: dq 0Ah
num2B: dq 0Ah
result: dq 00h
如果您仍想添加两个字节并将结果存储在另一个字节中,请使用8位寄存器,或使用movzx/movsx
指令将一个字节的内容零/符号扩展为完整的64位寄存器
_start: ;8-bit register version
mov al, 0
add al, [num1B]
add al, [num2B]
mov [result], al
movzx rdx,byte ptr [result]
_start: ;MOVZX version
movzx rax,byte [num1B]
movzx rbx,byte ptr [num2B]
add rax,rbx
mov [result],al
movzx rdx,[result]
答案 1 :(得分:2)
根据Intel guidelines在64位Intel架构上进行数据对齐,
在16位英特尔架构下,数据对齐对性能影响不大,其使用完全是可选的。在IA-32下,正确对齐数据可能是一项重要的优化,尽管它的使用仍然是可选的,只有极少数例外,其中必须正确对齐。但是,64位环境对数据项提出了更严格的要求。未对齐的对象会导致程序异常。
我不确定这个问题是否适用于此,但我认为num1B, num2B,
和result
分配了单个字节,而mov
则使用了64位寄存器在代码中将尝试取多个未对齐的字节。如果问题不对齐,则可能是在.data
部分结束时阅读。