x86 汇编 CPU 是如何使用 loop 指令的操作数的? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
amiwrong123

x86 汇编 CPU 是如何使用 loop 指令的操作数的?

  •  
  •   amiwrong123 2023 年 1 月 10 日 1842 次点击
    这是一个创建于 1200 天前的主题,其中的信息可能已经有所发展或是发生改变。

    loop 指令的功能是重复执行一段相同的代码,处理器在执行它的时候会顺序做两件事:

    • 将寄存器 CX 的内容减一;
    • 如果 CX 的内容不为零,转移到指定的位置处执行,否则顺序执行后面的指令。

    和 jmp near start 一样,loop digit 后跟的操作数也是一个相对的偏移量,是在编译阶段,编译器用标号 digit 所在位置的汇编地址减去 loop 指令的汇编地址,再减去 loop 指令的长度( 2 )来得到的。

     ;计算各个数位 mov bx,ax mov cx,5 ;设置循环次数 mov si,10 ;除数 digit: xor dx,dx div si mov [bx],dl ;保存数位 inc bx loop digit 

    图为 lst 文件的内容。

    上面 loop 指令的操作数0xF7,编译阶段是这么算出来的。0x43 - 0x4A - 0x2 = -9,而-9 截取一个字节的话,就是 F7.

    现在的问题是 cpu 是如何使用 loop 指令的操作数的?我是这么猜的:

    1. 取出 loop 指令自己所在地址的低 8bit 4A ,然后0x4A + F7 + 2 = 0x143
    2. 然后对 0x143 截取低 8bit ,为 0x43
    3. 然后把自己的地址0x0000_004A的低 8bit 替换为算出来的0x43,得到 要跳转的地址0x0000_0043

    不知道对不对?

    8 条回复    2023-01-11 00:30:36 +08:00
    cpstar
        1
    cpstar  
       2023 年 1 月 10 日
    似乎有一个指令地址寄存器,0xf7 直接与指令地址寄存器相计算得到新的指令地址。然后汇编里都是相对地址,实际地址还要有段基址等东西。
    cpstar
        2
    cpstar  
       2023 年 1 月 10 日
    另外,指令地址寄存器应该是在遇到 0x4A 的 E2 ,继续读取 0x4B 作为操作数,然后滑向了 0x4C ; 0x4B 的操作数是一个有符号整数,所以按照补码进行加法,获得了新的地址指向 0x43 位置
    amiwrong123
        3
    amiwrong123  
    OP
       2023 年 1 月 10 日
    @cpstar #2
    你说的有点道理,不过感觉 CPU 处理有点麻烦阿,

    因为自身的地址 0x0000_004A 是要作为无符号数的,然后操作数则要作为一个 有符号数 来处理(毕竟还可能向 第 9 个 bit 产生进位或借位)。
    Mohanson
        4
    Mohanson  
       2023 年 1 月 10 日
    CPU 有个 PC 寄存器, 在执行 loop 前 PC = 0000004A, 将 loop 指令取指后 PC = 0000004A + 2, 之后解码, 得到偏移立即数 0xF7(-9), 最后执行 loop 指令, 如果 ecx !=0, 令 PC = 0000004A + 2 - 9 = 00000043; 如果 ecx == 0, 则不修改 PC.
    Mohanson
        5
    Mohanson  
       2023 年 1 月 10 日
    补充一下上面: 执行 loop 指令, 判断 ecx 是否等于 0 之前有一步 ecx -= 1 的步骤
    billlee
        6
    billlee  
       2023 年 1 月 10 日
    「会顺序做两件事」这个理解就不对,所有操作都是一个时钟周期内完成的,就是一个 CX_out, PC_out = f(CX_in, PC_in) 的组合逻辑,非常简单的一个指令。
    secondwtq
        7
    secondwtq  
       2023 年 1 月 11 日
    1. 不要完全用软件的思路揣测硬件实现,硬件可以定制任意位数的加法器的 ...
    2. 不止 LOOP ,JMP 就很常用这样的模式
    3. 由于各种原因,LOOP 这条指令基本早就不用了,编译器也不会生成。
    mxT52CRuqR6o5
        8
    mxT52CRuqR6o5  
       2023 年 1 月 11 日 via Android
    4A 处的 loop 指令长度为 2 个字节,下一条指令的地址为 0x4C ,0x4C+0xF7 = 0x43 ,不然这个+2 也太 magic number 了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1070 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 43ms UTC 18:28 PVG 02:28 LAX 11:28 JFK 14:28
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86