Compilation 手动编译程序集

Compilation 手动编译程序集,compilation,assembly,Compilation,Assembly,我在将汇编中的特定行转换为机器代码时遇到问题。 我已经成功地编译了这些行: START_TIMER = 0xF68C r0 = 0x0 r8 = 0x8 label = 50000 #orhi r8, r0, %hiadj(label) --> 00000 01000 ???????????????? 110010 addi r8, r8, %lo(label) --> 01000 01000 1100001101010000 000100 subi r8, r8, 1 -->

我在将汇编中的特定行转换为机器代码时遇到问题。 我已经成功地编译了这些行:

START_TIMER = 0xF68C
r0 = 0x0
r8 = 0x8
label = 50000

#orhi r8, r0, %hiadj(label) --> 00000 01000 ???????????????? 110010
addi r8, r8, %lo(label) --> 01000 01000 1100001101010000 000100
subi r8, r8, 1 --> 01000 01000 1111111111111111 000100
bne r8, r0, START_TIMER --> 01000 00000 1111011010001100 011110
在这一行中,我遇到的问题是IMM16:

orhi r8, r0, %hiadj(label)
如上面链接的手册中所述,“%lo”表示“immed32的提取位[15..0]”,“%hiadj”表示“提取位[31..16]并添加immed32的位15”。然而,50000在二进制中是1100001101010000,因此是一个16位的数字。据我所知,它不包含16到31之间的任何位。我尝试使用00000000000000001,但它不正确

我做错了什么

编辑: 只是为了消除误解;我只想知道如何手动编译“orhi r8,r0,%hiadj(标签)”。变量“r8”、“r0”和“label”如上所述,不会改变

编辑2: 我尝试将50000转换为32位二进制:

00000000000000001100001101010000
…提取位[31…16]:

0000000000000000
…添加第15位(这令人困惑,因为他们没有告诉我它值2^15还是2^0,我已经尝试了这两种方法,只是根本不添加)

所有这些都是错误的

编辑3:
根据,当16位值为0x8000或更大时,它会将其余的扩展到0xFF8000,并在位[31…16]中添加1,这会将数字重载到0x10000800~0x00008000,这就是您所说的,Jerald,但显然仍然不正确。

您提供的代码采用“label”处的值,这是一个16位半字,并将其扩展到32位字以成为地址。由于标签是16位值,因此必须将零移到寄存器的上半部分

所以你要做的是把零加载到高位,然后加上低位

orhi  r8, r0, %hiadj(label) --> 00000 01000 0000000000000000 110010
addi  r8, r8, %lo(label) --> 01000 01000 1100001101010000 000100

“orhi”和“addi”是伪指令“movia”(movia r850000)的一部分,因此它直接出现在“addi”之前。除了这四条指令之外,没有其他指令提供给我,所以它不是一个完整的程序,只是一个片段。当你说“将位移到[31…16]”时,你的意思是我应该把它变成11000011010100000000000000000000吗?我对汇编编程很陌生,所以请耐心听我说。谢谢,但这也不正确。我很困惑,因为它说“提取位[31…16](都是零)并添加位15”。因为位15已经是1,所以它应该结转到位16,因此是00000000000000 1,但两者都不正确……0xFFFF是有符号的16位数字,所以它实际上是-1。将较低16位数字的高位相加将仅为-1+1=0。这是16位高位的0。我看到你的r8寄存器有一个值0x08。您的意思是这样做,还是应该是0x00?当您“或”寄存器时设置位3将保留位3。很抱歉,我在输入数字时犯了一个简单的错误。你是对的。谢谢:]
orhi  r8, r0, %hiadj(label) --> 00000 01000 0000000000000000 110010
addi  r8, r8, %lo(label) --> 01000 01000 1100001101010000 000100