Gcc 有没有办法在gnu汇编常量中使用数学表达式?
执行以下操作的正确gnu汇编语法是什么:Gcc 有没有办法在gnu汇编常量中使用数学表达式?,gcc,assembly,x86-16,gnu-assembler,osdev,Gcc,Assembly,X86 16,Gnu Assembler,Osdev,执行以下操作的正确gnu汇编语法是什么: .section .data2 .asciz "******* Output Data ********" total_sectors_written: .word 0x0 max_buffer_sectors: .word ((0x9fc00 - $data_buffer) / 512) # <=== need help here .align 512 data_buffer: .asciz "<The actual data wil
.section .data2
.asciz "******* Output Data ********"
total_sectors_written: .word 0x0
max_buffer_sectors: .word ((0x9fc00 - $data_buffer) / 512) # <=== need help here
.align 512
data_buffer: .asciz "<The actual data will overwrite this>"
这让我感到困惑,因为我需要标签的内存地址时应该使用$
,对吗
(2) 如果使用data\u buffer
而不是$data\u buffer
,则会出现以下错误:
os_src/boot.S: Assembler messages:
os_src/boot.S:497: Error: missing ')'
os_src/boot.S:497: Error: can't resolve `L0' {*ABS* section} - `$data_buffer' {*UND* section}
os_src/boot.S: Assembler messages:
os_src/boot.S:497: Error: missing ')'
os_src/boot.S:497: Error: value of 653855 too large for field of 2 bytes at 31
make: *** [obj/boot/dd_test.o] Error 1
这似乎表明汇编程序正在抱怨中间值的大小(不需要放入16位字)
(3) 当然,缺少“')”是怎么回事?在GNU汇编程序中使用表达式时,它们必须解析为绝对值。GNU汇编器不知道代码的原点实际在哪里。这就是链接器的用途。由于
数据\u缓冲区
绝对地址在链接完成之前是未知的,因此被认为是可重新定位的。如果取一个绝对值,如0x9fc00,然后从中减去一个可重定位值,则得到一个可重定位值。不能在常量(绝对)表达式中使用可重定位值
一切都没有失去。一旦链接器安排了内存中的所有内容,它自己就会知道绝对地址。您似乎建议您已经使用了链接器脚本,这意味着您需要做的工作非常少。您可以使用链接器计算max\u buffer\u扇区的值
链接器脚本将有一个部分
指令,如:
SECTIONS
{
[your section contents here]
}
您可以创建链接器符号max\u buffer\u sectors
,如下所示:
SECTIONS
{
max_buffer_sectors = (0x9fc00 - (data_buffer)) / 512;
[your section contents here]
}
这将允许链接器计算大小,因为它将知道内存中的data\u buffer
绝对地址
您的GNU程序集文件需要进行一些调整:
.globl data_buffer
.section .data2
.asciz "******* Output Data ********"
total_sectors_written: .word 0x0
.align 512
data_buffer: .asciz "<The actual data will overwrite this>"
您不应该使用$
。即便如此,你所能做的还是有限的。另外请注意,对于16位代码,通常使用多段和gas不是一个好主意。PS:我的汇编程序(v2.22)抱怨“-”的操作数(*ABS*和.data2部分)无效,这至少有道理。为什么$
在这种情况下不合适?(我发现这是反复试验的结果,但我仍然不清楚何时使用$
)(另请参见)我的玩具操作系统以实模式启动,切换到保护模式运行“常规”32位代码,然后在最后返回实模式,将内存缓冲区转储回磁盘。如果gas不是16位代码的正确工具,那么什么是好的替代方案?使用nasm编译16位代码,使用gcc编译其余代码并将其全部链接怎么样?$
只是指令中立即数操作数的信号,它告诉汇编程序发出立即数而不是有效地址。它也适用于整个操作数,而不是符号,例如,movl$4+foo,%eax
是合法的。是的,您可以使用nasm
,但通常不希望链接16位和32位代码。让nasm生成平面二进制输出,并根据需要使用构建系统来构建图像。转换通常通过固定地址进行。
mov $max_buffer_sectors, %ax