您所看到的代码旨在在具有 BIOS 的基于 x86 的 PC 上以实模式运行。Int 0x10 http://www.ctyme.com/intr/int-10.htm是一个 BIOS 服务,能够写入控制台。尤其Int 0x10/AH=0x0e http://www.ctyme.com/intr/rb-0106.htm是将单个字符写入 TTY(终端)。
这本身并不能解释约束的含义。了解限制条件Rah
and Ral
您必须了解此代码不是由标准版本的 GCC/CLANG 编译的。它正在由一个名为的 GCC 端口编译ia16-gcc https://github.com/tkchia/gcc-ia16。它是一个针对 8086/80186 和 80286 及兼容处理器的特殊端口。它不会生成 386 条指令,也不会在代码生成中使用 32 位寄存器。这实验性的GCC 版本的目标是 16 位环境,例如 DOS(FreeDOS、MSDOS),以及ELKS http://elks.sourceforge.net/.
的文档ia16-gcc
很难在网上找到 HTML 格式的,但我为最近制作了一份副本GitHub 上的 GCC 6.3.0 版本文档 https://mpetch.github.io/ia16-gcc-6.3.0/gcc/index.html。该文档是通过从源代码构建 ia16-gcc 并使用make
生成 HTML。如果您查看 Intel 的机器限制IA-16—配置/ia16您现在应该能够看到发生了什么:
Ralal 寄存器。
Rah啊寄存器。
这个版本的 GCC 不理解R
不再受到自身的约束。您正在查看的内联程序集与参数相匹配整数 0x10/Ah=0xe http://www.ctyme.com/intr/rb-0106.htm:
VIDEO - TELETYPE OUTPUT
AH = 0Eh
AL = character to write
BH = page number
BL = foreground color (graphics modes only)
Return:
Nothing
Desc: Display a character on the screen, advancing the cursor
and scrolling the screen as necessary
其他信息
该文档确实列出了 IA16 目标可用的所有约束:
Intel IA-16—config/ia16/constraints.md
a
The ax register. Note that for a byte operand,
this constraint means that the operand can go into either al or ah.
b
The bx register.
c
The cx register.
d
The dx register.
S
The si register.
D
The di register.
Ral
The al register.
Rah
The ah register.
Rcl
The cl register.
Rbp
The bp register.
Rds
The ds register.
q
Any 8-bit register.
T
Any general or segment register.
A
The dx:ax register pair.
j
The bx:dx register pair.
l
The lower half of pairs of 8-bit registers.
u
The upper half of pairs of 8-bit registers.
k
Any 32-bit register group with access to the two lower bytes.
x
The si and di registers.
w
The bx and bp registers.
B
The bx, si, di and bp registers.
e
The es register.
Q
Any available segment register—either ds or es (unless one or both have been fixed).
Z
The constant 0.
P1
The constant 1.
M1
The constant -1.
Um
The constant -256.
Lbm
The constant 255.
Lor
Constants 128 … 254.
Lom
Constants 1 … 254.
Lar
Constants -255 … -129.
Lam
Constants -255 … -2.
Uo
Constants 0xXX00 except -256.
Ua
Constants 0xXXFF.
Ish
A constant usable as a shift count.
Iaa
A constant multiplier for the aad instruction.
Ipu
A constant usable with the push instruction.
Imu
A constant usable with the imul instruction except 257.
I11
The constant 257.
N
Unsigned 8-bit integer constant (for in and out instructions).
有许多新的限制和一些重新调整用途的限制。
特别是a
AX 寄存器的约束不像其他针对 32 位和 64 位代码的 GCC 版本那样工作。编译器可以自由选择AH or AL与a
约束if传递的值是 8 位值。这意味着有可能a
约束在扩展内联汇编语句中出现两次。
您可以使用以下命令将代码编译为 DOS EXE:
ia16-elf-gcc -mcmodel=small -mregparmcall -march=i186 \
-Wall -Wextra -std=gnu99 -O3 int10h.c -o int10h.exe
它针对的是 80186。您可以通过省略来生成 8086 兼容代码-march=i186
生成的代码为main
看起来像:
00000000 <main>:
0: 83 f8 01 cmp ax,0x1
3: 7e 1d jle 22 <tty_write_string+0xa>
5: 56 push si
6: 89 d3 mov bx,dx
8: 8b 77 02 mov si,WORD PTR [bx+0x2]
b: 8a 04 mov al,BYTE PTR [si]
d: 20 c0 and al,al
f: 74 0d je 1e <tty_write_string+0x6>
11: 31 db xor bx,bx
13: b4 0e mov ah,0xe
15: 46 inc si
16: cd 10 int 0x10
18: 8a 04 mov al,BYTE PTR [si]
1a: 20 c0 and al,al
1c: 75 f7 jne 15 <main+0x15>
1e: 31 c0 xor ax,ax
20: 5e pop si
21: c3 ret
22: 31 c0 xor ax,ax
24: c3 ret
当使用命令行运行时int10h.exe "Hello, world!"
应该打印:
你好世界!
特别提示:GCC 的 IA16 端口是非常实验性的,并且确实存在一些代码生成错误,特别是在使用更高的优化级别时。目前我不会将它用于关键任务应用程序。