鱼C论坛

 找回密码
 立即注册
查看: 980|回复: 5

[已解决]汇编语言的一段代码不理解,有很多不懂的地方

[复制链接]
发表于 2023-5-20 19:58:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
assume cs:code
data segment                  ;定义数据段(俺也不太懂它的作用,只知道它可以用来定义变量)
     VARM1 dw ’1‘    ;定义变量VARM1
     VARB db 12 dup(0)     ;同上
     VARM dw 16 dup(0)
data ends
code segment                 ;定义代码段
start:mov bl,0                 
      mov ax,VARW1        ;怎么感觉把VARW1当成寄存器了,不理解
          add ax,0              ;0和ax相加不还是ax吗?有啥用
          js done                 ;有符号就跳转,也就是最高位为“1”就跳转,然后done就可以记下左移次数和结果
GOON: INC bl                 ;也就是说,执行完上面的操作之后发现最高位不是“1”就bl自加1?这样不就只加一次吗?万一要移很多次呢?
      add ax,ax               ;左移(为啥?)
          cmp ax,0
done:mov VARM,ax        ;保存左移后的结果
     mov VARB,bl             ;保存左移次数
code ends
end start
;将字变量VARM1中的非零数据左移到最高位为“1”止,
;左移次数存入字节变量VARB中,左移后的结果保存入字变量VARM中
我想实现以上功能,但是我对汇编一窍不通,注释是一点点理解,想请问一下我该怎么根据错误来改正呀


                               
登录/注册后可看大图

最佳答案
2023-5-20 19:59:25
这段汇编代码的作用是将变量VARM1中的非零数据左移,直到最高位为1止,同时记录左移次数和左移后的结果。下面是对代码中一些不理解的地方的解释:

1. 数据段用于定义程序中需要用到的变量,包括全局变量和局部变量等。在这段代码中,VARM1、VARB和VARM都是定义的变量。

2. mov ax, VARW1这一行代码的作用是将变量VARW1中的值赋给寄存器ax。可能是笔误,应该是VARM1。

3. add ax, 0这一行代码的作用是将寄存器ax中的值加上0,实际上没有任何作用,可以直接省略。

4. js done这一行代码的作用是判断ax寄存器中的值是否为负数(即最高位为1),如果是负数则跳转到done处执行相应的操作。

5. INC bl这一行代码的作用是将寄存器bl中的值加1,用于记录左移次数。

6. add ax, ax这一行代码的作用是将寄存器ax中的值左移一位,相当于乘以2。

7. 比较指令cmp ax, 0的作用是将寄存器ax中的值与0进行比较,如果相等则跳转到done处执行相应的操作。

总的来说,这段代码的实现思路是将变量VARM1中的值左移,每左移一次就将左移次数加1,直到最高位为1时停止左移,并将左移后的结果保存到变量VARM中。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-20 19:59:25 | 显示全部楼层    本楼为最佳答案   
这段汇编代码的作用是将变量VARM1中的非零数据左移,直到最高位为1止,同时记录左移次数和左移后的结果。下面是对代码中一些不理解的地方的解释:

1. 数据段用于定义程序中需要用到的变量,包括全局变量和局部变量等。在这段代码中,VARM1、VARB和VARM都是定义的变量。

2. mov ax, VARW1这一行代码的作用是将变量VARW1中的值赋给寄存器ax。可能是笔误,应该是VARM1。

3. add ax, 0这一行代码的作用是将寄存器ax中的值加上0,实际上没有任何作用,可以直接省略。

4. js done这一行代码的作用是判断ax寄存器中的值是否为负数(即最高位为1),如果是负数则跳转到done处执行相应的操作。

5. INC bl这一行代码的作用是将寄存器bl中的值加1,用于记录左移次数。

6. add ax, ax这一行代码的作用是将寄存器ax中的值左移一位,相当于乘以2。

7. 比较指令cmp ax, 0的作用是将寄存器ax中的值与0进行比较,如果相等则跳转到done处执行相应的操作。

总的来说,这段代码的实现思路是将变量VARM1中的值左移,每左移一次就将左移次数加1,直到最高位为1时停止左移,并将左移后的结果保存到变量VARM中。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-20 20:08:45 | 显示全部楼层
isdkz 发表于 2023-5-20 19:59
这段汇编代码的作用是将变量VARM1中的非零数据左移,直到最高位为1止,同时记录左移次数和左移后的结果。下 ...

首先感谢解答,还有不明白的是第5点说到INC bl的作用是bl的值+1,记录左移次数,看代码他只执行了一次,是不是代表bl的值最大就是1?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-20 20:13:31 | 显示全部楼层
倔强青铜铜 发表于 2023-5-20 20:08
首先感谢解答,还有不明白的是第5点说到INC bl的作用是bl的值+1,记录左移次数,看代码他只执行了一次, ...

INC bl 的确只是将 bl 的值增加1,但你需要注意到这一指令在一个循环中。循环开始于 start 标签,并在 GOON 标签的前面结束,条件为当 ax 的最高位为 1 时(即ax为负数时,因为js指令是检测“负数溢出”),它将跳转到 done 标签处。

如果 ax 的最高位不是 1,那么程序就会返回到 GOON,再次执行 INC bl。这个过程会重复,直到 ax 的最高位为 1 为止。因此,INC bl 可能会执行多次,所以 bl 的值可能会大于1,即左移的次数可能会大于1。这也是你提到的“左移到最高位为1”过程的实现方式。

需要注意的是,你的代码里面缺少了循环的跳转部分,你应该在代码中添加 jmp GOON 指令。代码应修改为:
start:mov bl,0                 
      mov ax,VARM1        
      add ax,0              
      js done                 
GOON: INC bl                 
      add ax,ax               
      cmp ax,0
      jns GOON ;添加这行来进行跳转
done:mov VARM,ax        
     mov VARB,bl 

这样,只有当 ax 的最高位为 1(即ax为负数)时,它才会跳出循环,否则它会不断地返回 GOON,bl 的值会持续增加,代表着左移的次数。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2023-5-20 20:16:08 | 显示全部楼层
isdkz 发表于 2023-5-20 20:13
INC bl 的确只是将 bl 的值增加1,但你需要注意到这一指令在一个循环中。循环开始于 start 标签,并在 GO ...

感谢!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-20 21:18:38 | 显示全部楼层
倔强青铜铜 发表于 2023-5-20 20:08
首先感谢解答,还有不明白的是第5点说到INC bl的作用是bl的值+1,记录左移次数,看代码他只执行了一次, ...


首先,在这段代码中出现了一些错误和问题:

VARW1 这个变量在数据段中没有被定义,应该改为 VARM1。

add ax,0 这行代码没有实际意义,可以直接删去。

js done 这个条件跳转是错误的,应该使用 jns done,表示只有最高位不是 1 的时候才跳转到 done 标签,否则就继续执行下面的代码。

在 GOON 标签后的代码中,应该使用 jl done 条件跳转到 done 标签,因为当左移次数超过 16 次时(即最高位已经移动到了最低位),程序应该结束。

在保存左移结果和左移次数时,应该使用 mov word ptr VARM, ax 和 mov byte ptr VARB, bl,因为 VARM 是一个双字(4 字节)变量,而 ax 寄存器只有 2 字节;而 VARB 是一个字节变量,而 bl 寄存器只有 1 字节,需要使用 byte ptr 显式指定存储数据的大小。

修改后的代码如下:
data segment
    VARM1 dw '1'
    VARB db 12 dup(0)
    VARM dw 16 dup(0)
data ends

code segment
start:
    mov bl, 0
    mov ax, VARM1
check:
    jns done
goon:
    inc bl
    add ax, ax
    cmp bl, 16
    jl done
    jmp check
done:
    mov word ptr VARM, ax
    mov byte ptr VARB, bl
    ; 程序结束
code ends
end start
这个程序的主要逻辑是检查 VARM1 中二进制表示中最高位为 1 的位置,然后将其左移至最高位,并记录左移的次数和结果。具体来说,程序首先将 VARM1 的值赋给 ax 寄存器,然后不断将 ax 左移,并使用 bl 记录左移的次数,直到最高位(即符号位)为1。最后,程序将左移后的结果保存在 VARM 变量中,将左移次数保存在 VARB 变量中。


针对你的“还有不明白的是第5点说到INC bl的作用是bl的值+1,记录左移次数,看代码他只执行了一次,是不是代表bl的值最大就是1?”,我的回答是:不是的,INC bl 表示将 bl 中的值加 1,也就是说在 GOON 标签后,每执行一次 INC bl,就意味着左移次数加 1。程序会一直循环执行 GOON 标签后的代码,直到左移次数超过了 16 次(即最高位已经移动到了最低位),或者已经左移至最高位为 1。所以实际上 bl 的值可能会达到 16,并不止是 1。

有用请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-22 00:35

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表