首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >难以解释内联汇编程序代码中的取消引用操作数

难以解释内联汇编程序代码中的取消引用操作数
EN

Stack Overflow用户
提问于 2015-10-14 20:12:55
回答 1查看 156关注 0票数 0

tl;dr在底部。

除了几年前在System上编程之外,我没有使用汇编程序的经验。此外,据我所知,汇编程序中存在类型信息--但是这里没有给出任何信息,因此显然类型是从提供给代码的C++变量中推断出来的。

我要处理掉它。意味着我得分辨出它是干什么的。显然这比我想象的要难:

案例一:

代码语言:javascript
运行
复制
  push eax
  push ebx
  push ecx
  push edx
  push esi
  push edi

  mov esi, data
  mov edi, screen
  xor eax, eax
heightloop2: // do {
  mov edx, width1
  neg edx
widthloop2: // do {
  mov eax, [esi + edx*8] // screen[b] = data[b]
  mov ecx, 4[esi + edx*8] // screen[b] = data[b]
  mov [edi + edx*8], eax
  mov 4[edi + edx*8], ecx

  add edx, 1 // b += 1
  js widthloop2 // } while(b)

  add edi, destpitch // screen += SCREEN_WIDTH
  add esi, datapitch // data += datapitch
  dec counter
  jnz heightloop2 // } while(a)

  //emms

  pop edi
  pop esi
  pop edx
  pop ecx
  pop ebx
  pop eax

案例2:

代码语言:javascript
运行
复制
  push eax
  push ebx
  push ecx
  push edx
  push esi
  push edi

  mov esi, data
  mov edi, screen
  xor eax, eax
  mov ecx, transcol
heightloop: // do {
  mov ebx, 0
  mov edx, width1
  neg edx
widthloop: // do {
  mov ax, [esi + ebx*2] // screen[b] = data[b]
  add ebx, step // b += 1

  cmp eax, ecx // Check for transparent color
  je trans

  mov [edi + edx*2], ax
trans:
  add edx, 1 // b += 1
  jnz widthloop // } while(b)

  add edi, destpitch // screen += SCREEN_WIDTH
  add esi, datapitch // data += datapitch
  dec counter
  jnz heightloop // } while(a)

  //emms

  pop edi
  pop esi
  pop edx
  pop ecx
  pop ebx
  pop eax

这些评论不是我的,它们是我必须要处理的。

两者都有类似的投入:

代码语言:javascript
运行
复制
unsigned char * data, screen
uint32_t * palette
int counter, datapitch, destpitch, step, transcol, width1

现在,很容易看出(除非我弄错了,请纠正这种情况),这两种情况的控制流是相等的:

代码语言:javascript
运行
复制
do
{
  // int a = 0; // additionally in case 2
  int b = -weight1;
  do
  {
    <work>
  }
  while(++b < 0); // actually ++b != 0 in case 2, but symptoms should be equal
  screen += destpitch;
  data += datapitch;
}
while(--counter != 0);

现在,“工作”部分略有不同。有两件事让我彻底困惑:

  • 两个第一个mov指令都有相同的注释--但删除地址的计算方式不同。这怎么能结合在一起呢?这里的因素到底是什么?
  • Case 2有另一个mov集,在取消引用括号前面有一个数字前缀。我在各种参考资料中找不到这个成语。这句话是什么意思?

不幸的是,VS2015调试器将这些代码示例中的所有值作为“无符号int”发送--我几乎可以肯定这是不正确的(同样,如果我错了,请更正)。

因此,简明扼要:

  • 请验证或更正我的推断控制流.
  • 请解释或链接到对这些移动指令的解释.

使用@Jester的指针,我能够用执行相同操作的C++代码替换这两种情况:

案例1:

代码语言:javascript
运行
复制
  do
  {
    for(int b = -width1; b < 0; ++b)
      memcpy(screen + b * 8, data + b * 8, 8u);

    screen += destpitch;
    data += datapitch;
  }
  while(--counter != 0);

案例2:

代码语言:javascript
运行
复制
  do
  {
    int a = 0;
    for(int b = -width1; b != 0; ++b)
    {
      const uint16_t * const c = (uint16_t*)(data + a * 2);
      if(transcol != *c)
        memcpy(screen + b * 2, c, 2u);
      a += step;
    }
    screen += destpitch;
    data += datapitch;
  }
  while(--counter != 0);

当然,看看这个,很明显,它可以写得更优雅,但我决定把它留在这里,这样转换就更明显了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-14 20:28:59

该因子是按元素大小缩放的。如您所见,第一种情况处理8字节单位,第二种情况处理2字节单位。

括号外的数字是数组语法的特例。顺便说一句,在C中也可以这样做:5[array]array[5]是一样的。在“正常”的英特尔语法中,您只需将数字插入括号中,例如mov [edi + edx*8 + 4], ecx

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33134739

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档