我正在阅读Micheal Abrash的图形编程黑皮书(顺便说一句,我很享受,我强烈推荐它),所以我正在使用的示例代码已经很老了。尽管如此,我不知道问题是什么:
__asm__(
//Some setup code here
"movl %%esi, %%edi;"
"movw %%ds, %%es;"
//A whole bunch more assembly code in between
"divloop:"
"lodsw;"
"divl %%ebx;"
"stosw;"
"loop divloop;"
//And a little more code here
: "=r" (ret)
: "0" (ret) /*Have to do this for some reason*/, "b" (div), "c" (l), "S" (p)
: "%edi", "%es"
);
l
变量是unsigned int,p
变量是char *。 l
是p
指向的字符串长度的字节数。 div
是除数,是一个无符号整数。 ret
是返回值(an
unsigned int)函数并在程序集块内部设置
是该师的其余部分。我得到的错误消息是“错误:'asm'中的未知寄存器名'%es'”(这是唯一的错误消息)。我最好的猜测是它在GAS语法中有另一个名字。我知道我正在使用旧代码,但据我所知,在我相当新的intel i3上仍有一个ES寄存器被stos使用*
其次,有一个问题一直困扰着我。我基本上别无选择只能假设DS已经设置到正确的内存位置以便与lods *一起使用。由于我正在读取,修改和写入相同的内存位置(使用stos *和lods *),因此我将ES设置为等于DS。然而,我真的害怕我的DS可能是什么,我不知道还有什么可以设置它。更重要的是,ESI和EDI已经是32位寄存器,应该可以自己访问内存。
根据我的经验,两个奇怪的问题通常是相关的,并且由更基本的问题(通常是PEBKAC)引起。但是,我在这一点上很难过。有谁知道发生了什么事?
非常感谢
P.S。我正在尝试重新创建第9章(Hints My Readers Gave Me,清单9.5,第182页)中的代码,该代码通过EBX划分存储在连续内存中的大量数字。没有其他原因可以做到这一点,而不是我个人的成长和娱乐。
答案 0 :(得分:5)
如果您在平坦的32位保护模式环境(如Linux或Windows用户模式进程)中运行,则无需设置es。
段寄存器由OS设置,es和ds都允许您访问平坦的32位地址空间。
GCC不会生成保存/恢复段寄存器的代码,因此它不允许您将它们添加到clobber列表中也就不足为奇了。