【问题标题】:My own Improvised compiler error我自己的即兴编译器错误
【发布时间】:2013-12-18 11:59:42
【问题描述】:

我正在使用 Monodevelop 在 Linux 上的 C# 中构建 C 编译器的子集。 我的编译器从文件中读取文本并输出到程序集。 现在我首先要注意的是,我遇到的问题不是 C# 问题,而是程序集误解。我正在使用 nasm 汇编器和 gcc 链接器。 这是输出的程序集:

extern printf
extern strcpy
extern systemsame
extern readinput
extern getdest
section .text
global main
jmp main_over
main:
push rax
mov rax, 0
mov rax, 1
mov byte [a], al
pop rax
push rax
mov rax, 0
mov rax, 0
mov byte [b], al
pop rax
IF_STATEMENT_0:
cmp byte [a] , 1
jne IF_STATEMENT_0_over
mov rdi, QUOTE_0
mov rax, 0
call printf
ret
main_over: 
IF_STATEMENT_1:
cmp byte [a] , 0
jne IF_STATEMENT_1_over
mov rdi, QUOTE_1
mov rax, 0
call printf
ret
IF_STATEMENT_1_over: 
IF_STATEMENT_2:
cmp byte [a] , b
jne IF_STATEMENT_2_over
mov rdi, QUOTE_2
mov rax, 0
call printf
ret
IF_STATEMENT_2_over: 
IF_STATEMENT_3:
cmp byte [a], 0
je IF_STATEMENT_3
mov rdi, QUOTE_3
mov rax, 0
call printf
ret
IF_STATEMENT_3_over: 
IF_STATEMENT_4:
cmp byte [b], 0
je IF_STATEMENT_4
mov rdi, QUOTE_4
mov rax, 0
call printf
ret
IF_STATEMENT_4_over: 
ret
IF_STATEMENT_0_over: 
section .bss
a: resb 1
b: resb 1
tempbyte: resb 20
tempword: resw 20
tempdword: resd 20

section .data

;Passon extra bit from parsing state;;;
QUOTE_0: db "a is 1!", 0
QUOTE_1: db "a is 0!", 0
QUOTE_2: db "a is b!", 0
QUOTE_3: db "a is true!", 0
QUOTE_4: db "b is true!", 0

我用 nasm 汇编器编译它并得到 NO 错误和 NO 警告。 然后,我得到一个目标代码 (.o) 文件并将其与另一个 Working(经过测试的)目标代码文件(具有 systemsame()readinput()getdest() 的定义)链接 使用 gcc。我收到以下奇怪的错误:

In function `IF_STATEMENT_1_over':
outout.asm:(.text+0x71): relocation truncated to fit: R_X86_64_8 against `.bss'
collect2: error: ld returned 1 exit status

【问题讨论】:

  • 顺便说一句,如果我的汇编代码在某些地方不可读,我很抱歉。这是因为我的编译器远非完美。
  • 您编写了“另一个工作对象文件”,但仅仅因为两个对象文件本身都是合法的并不意味着它们可以很好地协同工作 - 阅读 ABI 了解更多信息。不是说这是问题的原因,只是评论。
  • 它适用于我以前版本的“编译器”,因此该对象绝对是合法的
  • 我的意思是,它与“合法性”无关;目标文件也需要使用相同的 ABI。
  • 但是还是不行:(

标签: assembly compiler-construction x86-64 nasm


【解决方案1】:

在我看来,错误很可能是cmp byte [a] , b,因为它就在错误消息中提到的标签之后,并且涉及在错误消息中提到的部分.bss 中定义的符号。该指令本身对我来说看起来很可疑,但确切的错误不是很清楚:可能b 的地址被用作立即数,这将涉及将其截断为 8 位。

仔细检查这确实是您想要的翻译。我怀疑您应该将b 的值加载到备用寄存器中,然后将其用作cmp 的第二个操作数。

附带说明,您应该为函数内部的基本块使用“本地”标签。否则,汇编器将浪费时间和空间来创建无用的重定位。通常这仅涉及以某种方式为这些标签添加前缀。例如,对于 GNU as,它是 .L - 请参阅您所针对的汇编程序的手册。

【讨论】:

    猜你喜欢
    • 2016-10-26
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 2010-09-10
    • 2011-05-08
    • 2012-06-05
    相关资源
    最近更新 更多