如果操作数超过127,CMP指令会有奇怪的行为?

我写了这个汇编程序。

.section .data
    1: .asciz "Hello"

.section .text

entry:
    mov $0x07C0, %ax
    add $0x120, %ax
    mov %ax, %ss
    mov 0x100, %sp

    mov $0x7C0, %ax
    mov %ax, %ds

    # mov $1b, %si
    mov $0xE, %ah
    mov $0x0, %si
    mov $0x0, %bx

    push %bp
    mov %sp, %bp
    mov %di, -20(%bp)
    mov %si, -32(%bp)

    movl $0x0, -4(%ebp)
.loopcond:
    cmpl $127, -4(%ebp)
    jge .halt
.print:
    lodsb
    int $0x10
    add $0x1, -4(%ebp)
    jmp .loopcond
.halt:
    jmp .halt

第一条指令 .loopcond 部分将变量比较为127(就像一个迭代127次的for循环)。这样做很好,在跳转到 .halt. 然而,当我增加要比较的值时(如128),代码似乎跳到了 .halt 立即。我不明白为什么会出现这种情况。是关于有符号整数比较的事情吗?

我看了objdump,有一次是127和128。

// 127:
00000037 <.loopcond>:
  37:   83 7d fc 7f             cmpl   $0x7f,-0x4(%ebp)
  3b:   7d 09                   jge    46 <.halt>

// 128:
00000037 <.loopcond>:
  37:   81 7d fc 80 00 00 00    cmpl   $0x80,-0x4(%ebp)
  3e:   7d 09                   jge    49 <.halt>

我注意到操作数 cmpl 指令在128的例子中是4个字节长,而在127的例子中只有1个字节。我怀疑是这方面的原因导致了这个错误。

解决方案:

您的问题可能与以下方面有关 add $0x1, -4(%ebp) 其中使用了一个模糊的操作数大小。 如果GAS选取字节操作数大小,可能会引起问题? 虽然如果上面的字节是零,那就只是零扩展到dword中。 你的问题原因并不明显,但你把BP和EBP的16位和32位地址大小混在一起就很奇怪了。

说真的,只要在寄存器里放一个数字,然后用循环 dec reg jnz 像个正常人一样。

或者使用调试器来查看内存,并整理出发生了什么。 你的 cmpl $127, -4(%ebp) 确实指定了操作数大小,所以它肯定是在做一个字比较,而不是处理为 128 作为 -128 与8位2的补码。

我注意到,在128的例子中,cmpl指令的操作数有4个字节长,而在127的例子中只有1个字节。我怀疑这一点是造成这个错误的原因。

这不是一个错误。 大多数基本的x86整数ALU指令都有一个操作码,一个版本有32位的立即,另一个版本有一个 符号扩展的8位立即.

在原来的8086上,这节省了1个字节的指令,如 cmp r/m16, imm8 与。cmp r/m16, imm16. 在3264位代码中,这为imm8与imm32节省了3个字节。 https:/www.felixcloutier.comx86cmp 列出了可用的表格。

截止点当然是-128 … +127,因为它是一个 标志-扩展的立即。 你的汇编器总是为给定的asm源码行选择尽可能小的编码,所以一切都按预期工作。


如果你在32位模式下组装,但以16位模式运行。cmpl $imm32, r/m32 将以不同于其他代码的方式中断.

其他指令无论模式如何都是相同的长度,但运行时操作数大小相反(16与32)。 但是操作码为 cmplcmpw 是一样的;不同的只是操作数大小(切换到非默认的模式值a)。66 前缀)。)

所以当你的 cmpl 在16位模式下组装成32位解码,有2个字节的即时剩余。 这些字节是 00 00,这是一个存储器-目的地 add [something], al (我忘了是哪一个登记处了。00 modrm在16位寻址模式下编码)。) 这将从 cmp.

使用 .code16 或命令行选项来制作16位机器代码。

给TA打赏
共{{data.count}}人
人已打赏
解决方案

获取Word字符串的函数

2022-5-13 15:00:20

解决方案

覆盖类型(String, Int, Boolean)的方法=>Double的类型不兼容。

2022-5-13 16:00:28

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索