鱼C论坛

 找回密码
 立即注册
查看: 5822|回复: 15

[已解决]还是一个有问题的程序,请指点一下

[复制链接]
发表于 2021-5-25 15:31:37 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 肖-肖 于 2021-5-25 15:37 编辑

题目是:
       实现:在270H开始的内存单元中存放了16个8位带符号数,找出其中最大和最小的数分别存入以280H和282H为首地址的内存单元
我的代码是:
  1. DATAS SEGMENT
  2.     ;此处输入数据段代码
  3.     org 0270H
  4.     n db 81H,70H,82H,76H,84H,74H,83H,78H,88H,71H,85H,73H,75H,86H,76H,87H          
  5. DATAS ENDS

  6. STACKS SEGMENT
  7.     ;此处输入堆栈段代码
  8. STACKS ENDS

  9. CODES SEGMENT
  10.     ASSUME CS:CODES,DS:DATAS,SS:STACKS
  11. START:
  12.     MOV AX,DATAS
  13.     MOV DS,AX
  14.     ;此处输入代码段代码
  15.     mov si,0270H
  16.     mov al,[si]
  17.     mov bl,al
  18.     mov cl,0FH
  19. ks:inc si
  20.     dec cl
  21.     jz over
  22.     cmp al,[si]
  23.     JLE next
  24.     mov al,[si]
  25. next:cmp bl,[si]
  26.         JG ks
  27.         mov bl,[si]
  28.         jmp ks
  29. over:mov si,0280H
  30.         mov [si],bl
  31.         add si,2
  32.         mov [si],al        
  33.     MOV AH,4CH
  34.     INT 21H
  35. CODES ENDS
  36.     END START
复制代码

我运行出来的结果是:
问3.png
我觉得如果看成是带符号数得话,88H不才是最小的那个负数吗? 我哪里不对?请指点一下,详细点(最好给个代码),我比较笨,谢谢了
最佳答案
2021-5-25 19:05:45
79 是最大,79 + 1 = 80
80 是最小
80 < 88

你的数据里面没有 80,最小是 81
没有 79,最大是 78

另一个问题,边界错误
试试这个代码,最后一个数据是 80,最小
  1. DATAS SEGMENT
  2.     ;此处输入数据段代码
  3.     org 0270H
  4.     n db 81H,70H,82H,76H,84H,74H,83H,78H,88H,71H,85H,73H,75H,86H,76H,80H
  5. DATAS ENDS

  6. STACKS SEGMENT
  7.     ;此处输入堆栈段代码
  8. STACKS ENDS

  9. CODES SEGMENT
  10. ASSUME CS:CODES,DS:DATAS,SS:STACKS
  11. START:
  12.     MOV AX,DATAS
  13.     MOV DS,AX
  14.     ;此处输入代码段代码
  15.     mov si,0270H
  16.     mov al,[si]
  17.     mov bl,al
  18.     mov cl,0FH
  19.     ;mov cl,10H
  20. ks: inc si
  21.     dec cl
  22.     jz over
  23.     cmp al,[si]
  24.     JLE next
  25.     mov al,[si]
  26. next:cmp bl,[si]
  27.     JG ks
  28.     mov bl,[si]
  29.     jmp ks
  30. over:mov si,0280H
  31.     mov [si],bl
  32.     add si,2
  33.     mov [si],al
  34.     MOV AH,4CH
  35.     INT 21H
  36. CODES ENDS
  37. END START
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-5-25 16:12:32 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-5-25 16:19:33 | 显示全部楼层


哦哦 您的意思是说:这么cmp相当于减,这个我知道,但是后边的那个表格说它之影响:ZF和CF对吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-5-25 16:21:24 | 显示全部楼层
肖-肖 发表于 2021-5-25 16:19
哦哦 您的意思是说:这么cmp相当于减,这个我知道,但是后边的那个表格说它之影响:ZF和CF对吗?

恩,是的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-5-25 16:22:05 | 显示全部楼层

不对吧
我查了下资料
资料如下
CMP比较指令使用寄存器Rn的值减去operand2的值,根据操作的结果影响新CPSR中相应的条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。CMP指令与SUBS指令的区别在于CMP指令不保存运算结果。在进行两个数据大小判断时,常用CMP指令及相应的条件码来操作。

CMP指令的格式为CMP op1 op2用到的标志位有CF,ZF,OF,SF四个,对于两个无符号数的情况,两数相减不可能溢出了,看CF和ZF标志位就可以,如果ZF为1,说明结果是0,那不用说,两数相等了(有符号数也是这样),如果ZF为0,则如果CF为1,表示有借位,op1<op2,否则op1>op2。

对于有符号数,就要看符号标志位SF和溢出标志位OF了,如果是两个同号的数,两数相减也是不可能溢出的,OF一定为0,此时,如果SF为1,则表示op1<op2,否则op1>op2,如果是两个异号的数相减,不溢出的情况跟上面的一样(OF==0,SF==1?op1<op2:op1>op2)。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-5-25 16:23:36 | 显示全部楼层
肖-肖 发表于 2021-5-25 16:22
不对吧
我查了下资料
资料如下

我用的JLE不是判断带符号数的大小吗?
省的去判断OF和SF了,挺麻烦的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-5-25 16:45:01 | 显示全部楼层
不好意思,上面的回复有点出入,刚翻了下 INTEL 手册,内容如下。

1621932067(1).jpg

1621932117(1).jpg

1621932161(1).jpg
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-5-25 19:05:45 | 显示全部楼层    本楼为最佳答案   
79 是最大,79 + 1 = 80
80 是最小
80 < 88

你的数据里面没有 80,最小是 81
没有 79,最大是 78

另一个问题,边界错误
试试这个代码,最后一个数据是 80,最小
  1. DATAS SEGMENT
  2.     ;此处输入数据段代码
  3.     org 0270H
  4.     n db 81H,70H,82H,76H,84H,74H,83H,78H,88H,71H,85H,73H,75H,86H,76H,80H
  5. DATAS ENDS

  6. STACKS SEGMENT
  7.     ;此处输入堆栈段代码
  8. STACKS ENDS

  9. CODES SEGMENT
  10. ASSUME CS:CODES,DS:DATAS,SS:STACKS
  11. START:
  12.     MOV AX,DATAS
  13.     MOV DS,AX
  14.     ;此处输入代码段代码
  15.     mov si,0270H
  16.     mov al,[si]
  17.     mov bl,al
  18.     mov cl,0FH
  19.     ;mov cl,10H
  20. ks: inc si
  21.     dec cl
  22.     jz over
  23.     cmp al,[si]
  24.     JLE next
  25.     mov al,[si]
  26. next:cmp bl,[si]
  27.     JG ks
  28.     mov bl,[si]
  29.     jmp ks
  30. over:mov si,0280H
  31.     mov [si],bl
  32.     add si,2
  33.     mov [si],al
  34.     MOV AH,4CH
  35.     INT 21H
  36. CODES ENDS
  37. END START
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-5-25 19:31:30 | 显示全部楼层
人造人 发表于 2021-5-25 19:05
79 是最大,79 + 1 = 80
80 是最小
80 < 88

第一个问题:
为什么一个字节有符号数中:79为最大正数这个我理解,那为什么80是最小的负数呢?80不应该代表0码?
还是说计算机中没有负数,看成是负数的话也是以补码的方式存放的?
比如81H-->源码--》1000 0001->反码--》1111 1110-》补码-》1111 1111-》FFH
比如89H-->源码->  1000 1001->反码->  1111 0110-> 补码-> 1111 0111-> F7H
那也应该是89H<81H啊?  为什么81H小? 如果直接看成-1也是它大
比如80H-->源码-->1000 0000-->反码-->1111 1111-->补码-->1000 0000 溢出

第二个问题:边界错误是指的什么?
我以为 是比较次数写错了,可是没错啊,就是:0FH 15次啊

   
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-5-25 20:13:13 | 显示全部楼层
肖-肖 发表于 2021-5-25 19:31
第一个问题:
为什么一个字节有符号数中:79为最大正数这个我理解,那为什么80是最小的负数呢?80不应该代表 ...

负数用补码表示
补码是 原码取反再加 1
举例
求 -1 在内存中的值
原码
00000001
取反
11111110
加 1
11111111
各位全 1,就是 -1
-1 + 1 = 0
11111111 + 00000001 = 1 00000000
最高位丢弃,结果就是 0

-128
原码 128 是
10000000
取反
011111111
加 1
100000000
最高位是 1,其他全 0,是 -128

可以看成最高位是符号位
011111111最大,0x79
100000000最小,0x80,这是有符号数 -128
100000001是0x81,是有符号数 -127

1 < 2
2 < 3
3 < 4
...
0x78 < 0x79
79是最大,再加 1,就变成了最小
0x80(-128) < 0x81(-127)
0x81(-127) < 0x82(-126)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-5-25 20:14:32 | 显示全部楼层
肖-肖 发表于 2021-5-25 19:31
第一个问题:
为什么一个字节有符号数中:79为最大正数这个我理解,那为什么80是最小的负数呢?80不应该代表 ...

你运行这个代码,看 282h 的内容,最小应该是 0x80
  1. DATAS SEGMENT
  2.     ;此处输入数据段代码
  3.     org 0270H
  4.     n db 81H,70H,82H,76H,84H,74H,83H,78H,88H,71H,85H,73H,75H,86H,76H,80H
  5. DATAS ENDS

  6. STACKS SEGMENT
  7.     ;此处输入堆栈段代码
  8. STACKS ENDS

  9. CODES SEGMENT
  10. ASSUME CS:CODES,DS:DATAS,SS:STACKS
  11. START:
  12.     MOV AX,DATAS
  13.     MOV DS,AX
  14.     ;此处输入代码段代码
  15.     mov si,0270H
  16.     mov al,[si]
  17.     mov bl,al
  18.     mov cl,0FH
  19.     ;mov cl,10H
  20. ks: inc si
  21.     dec cl
  22.     jz over
  23.     cmp al,[si]
  24.     JLE next
  25.     mov al,[si]
  26. next:cmp bl,[si]
  27.     JG ks
  28.     mov bl,[si]
  29.     jmp ks
  30. over:mov si,0280H
  31.     mov [si],bl
  32.     add si,2
  33.     mov [si],al
  34.     MOV AH,4CH
  35.     INT 21H
  36. CODES ENDS
  37. END START
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-5-25 20:50:59 | 显示全部楼层
人造人 发表于 2021-5-25 20:14
你运行这个代码,看 282h 的内容,最小应该是 0x80

我复制的代码 只粘贴个头好了
  1. DATAS SEGMENT
  2.     ;此处输入数据段代码
  3.     org 0270H
  4.     n db 81H,70H,82H,76H,84H,74H,83H,78H,88H,79H,85H,73H,75H,86H,76H,80H
  5. DATAS ENDS
复制代码

运行出来的是:
问2.png
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-5-25 20:52:10 | 显示全部楼层
肖-肖 发表于 2021-5-25 20:50
我复制的代码 只粘贴个头好了

运行出来的是:

应该是80才对呀,80最小
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-5-25 20:54:46 | 显示全部楼层
人造人 发表于 2021-5-25 20:52
应该是80才对呀,80最小

那是为什么?为什么会输出这个?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-5-25 20:59:43 | 显示全部楼层
人造人 发表于 2021-5-25 20:52
应该是80才对呀,80最小

哦 我知道了 是你说的那个边界问题 原来如此 因为我是将第一个数给了寄存器所以需要比较16次
应该是10H
我改了之后就对了
问3.png
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-5-25 21:03:16 | 显示全部楼层
人造人 发表于 2021-5-25 20:14
你运行这个代码,看 282h 的内容,最小应该是 0x80

感谢大佬 感谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-8 01:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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