在寄存器中存储unsigned char(x86程序集)

时间:2017-05-01 03:59:13

标签: c x86 inline-assembly

我正在编写一个传递了3个参数的函数。

void function(unsigned char* one, int two, unsigned char three) {
    __asm 
    {
            mov eax, one
            mov ebx, two
            mov ecx, three //Having issues storing this variable in a register

但是我得到了“三”的编译错误“操作数大小冲突”。另外两家商店就好了。我试图弄清楚为什么...如果我使用lea ecx, three它会编译。但是存储的值是错误的。

附带问题。我是否正确理解第一个参数是否为该变量传递了一个内存位置?

谢谢!

2 个答案:

答案 0 :(得分:1)

大多数x86指令要求所有参数都是相同大小。在这种情况下,three是一个8位参数,因此使用带有8位目标的mov来加载它,如mov cl, three

有一些mov类指令允许从更小的来源扩展到更大的目的地。例如,您可以使用movzx ecx, three(使用零扩展移动)将字节加载到ecx并将前三个字节归零。

答案 1 :(得分:0)

我建议不要通过“mov”指令显式地将参数移动到寄存器中,因为如果你已经将项目编译为“Register”调用约定,那么“one”,“two”和“three”只是别名寄存器和您可能会覆盖您需要的数据,只需在代码中插入不必要的“mov”指令即可。只需考虑什么参数进入什么寄存器并立即使用这些参数。但要注意尺寸小于寄存器大小的参数。较高的位可能未定义(已删除)。

这取决于特定的调用约定,但是,最可能的是,对于32位寄存器调用约定,调用在EAX中传递第一个参数,在EDX中传递第二个,在ECX中传递第三个。结果以EAX(32位)或EAX:EDX对(64位)返回。有关详细信息,请参阅http://docwiki.embarcadero.com/RADStudio/Seattle/en/Program_Control#Register_Convention

在你的情况下,“unsigned char three”立即出现在ECX中,EDX中的“two”和EAX中的“one”,你不需要做任何动作,但是因为“三”只是一个字符(8位) )并且ECX是双字(32位),ECX的位8-31可能包含垃圾。您不应该依赖于这些位为零的假设。

对于64位调用约定,第一个参数在RCX中传递,第二个 - RDX,第三个R8,第四个 - R9,结果在RAX中返回。有关64位的详细信息,请参阅https://msdn.microsoft.com/en-us/library/ms235286.aspx