什么MOV EAX,DWORD PTR DS:[ESI]意味着什么呢?

zet*_*eta 46 x86 assembly

好吧所以我在我的装配中有这条线

MOV EAX, DWORD PTR DS:[ESI]
Run Code Online (Sandbox Code Playgroud)

ESI是00402050(ascii,"123456789012")

在这个指示之后: EAX = 34333231

这里到底发生了什么?这个值是如何计算的,为什么?
我在哪里可以得到一些关于这类事情的好参考?

Hea*_*utt 69

方括号中的寄存器,例如[ESI]解除引用的指针.您引用的指令将DWORD(由32位/ 4字节值)移动ESI到寄存器指定的存储单元中EAX.在您的情况下,内存位置00402050,读作a DWORD,包含34333231.

写在伪C:

DWORD EAX;   /* Declaring the registers as we find them in silico */
DWORD ESI;

ESI = 0x00402050;  /* Set up your initial conditions for ESI */
EAX = *((DWORD *)ESI);   /* mov EAX, DWORD PTR [ESI] */
/*  ^ ^  ^^^^^^^    */
/*  | |     |       */
/*  | |     +-----------  From "DWORD PTR" we get "DWORD *" in C.          */
/*  | |             */ 
/*  | +-----------------  The C dereferencing operator * replaces [].      */
/*  |               */ 
/*  +-------------------  The C assignment operator = replaces mov opcode. */ 
Run Code Online (Sandbox Code Playgroud)

在你的情况下,0x00402050"等于"字符串并不是真的"1234567890"- 而是指向包含该字符串的内存.

您获得0x34333231的值由数字的ASCII值组成"1234",这些数字是DWORD字符串的前四个字节(即第一个字节).它们以相反的顺序出现,因为英特尔架构DWORD在内存的字节表示中是"小端" .

在您的示例中,当mov指令unsigned long实际上是一个单字节字符串时,指令正在加载ASCII字符,就像它们是值的四个字节一样.

  • 还应该提到的是`DS:[ESI]`表示法意味着`ESI`モ*在`DS`(数据段寄存器)偏移*从地址,所以该指令从地址移动双字(32位值) `DS + ESI`注册`EAX`. (37认同)
  • 我不是百分百肯定同意这个阶段的教学法.在保护模式下,DS是选择器,而不是段.我相信OP处于保护模式,因为Linux,Windows和MacOS都在支持VM的保护模式下运行,OP似乎不是嵌入式系统程序员.鉴于复杂的情况实际上非常简单(DS映射到整个地址范围而选择器基数为零),为什么要尝试剥洋葱? (14认同)
  • @Nikolai,我很高兴在这里提到一些'完整性'. (4认同)
  • 是的,对,至少是为了完整性.+1. (2认同)