我正在做一些关于 8086 实模式的工作。我习惯于在汇编中这样做,但想尝试一下 C 编译器。在我看来,编译器假定所有段寄存器都具有相同的值。我的情况并非如此。SS 为 0x4C0,而DS = ES = CS = 0x800。
因此,以下代码在编译时会生成代码,而不会考虑 SS <> DS 的事实。
[来源:这里]
uint8 ch;
void main()
{
uint8 hexchars[] = {'0','1','2','3','4','5','6','7','8','9','A','B',
'C','D','E','F'};
uint8 i = 0;
ch = hexchars[i];
}
编译后,作业产生:[完整来源:此处]
// ch = hexchars[i];
00000156 8A46FF mov al,[bp-0x1] ; 'i' is at [BP - 0x1]
00000159 30E4 xor ah,ah
0000015B 89C7 mov di,ax
0000015D 89EE mov si,bp
0000015F 89FB mov bx,di
00000161 8A40EF mov al,[bx+si-0x11 ; 'hexchars[0] is at [BP - 0x11]
00000164 A28401 mov [0x184],al ; 'ch' is at location 0x184
因为没有明确提到 SS,所以 DS 将由汇编程序假定。
如上所述,在我的情况下SS <> DS,因此 AL 现在具有来自错误地址的值。
移动铝,DS:[BX + SI - 0x11] <>移动铝,SS:[BX + SI - 0x11]
我尝试过的编译器:
1. GCC 版本 6.2.0 (Sourcery CodeBench Lite 2016.11-64)
ia16-elf-gcc -Wall main.c -o main.com -T main.ld
链接器文件如下:
OUTPUT_FORMAT(binary)
SECTIONS
{
. = 0x0;
.text :
{
*(.text);
}
.data :
{
*(.data);
*(.bss);
*(.rodata);
}
_heap = ALIGN(4);
/DISCARD/ :
{
*(.eh_frame)
}
}
2. Bruce 的 C 编译器[此处使用 BCC 的完整源代码]
bcc -ansi -0 -W -c main.c -o main.o
ld86 -d main.o -o main.com -T000
更新: 尝试了 SmallerC。这里再次编译器假设 SS = DS。
3. 较小的 C [来源]
smlrc -seg16 -Wall main.c main.s
nasm -f bin main.s -o main.com
结果在两个编译器中或多或少相同。从 stack 读取时,没有编译器明确指定 SS。问题是有一种方法可以通知编译器有关约束的信息,我是不是做错了什么。