网页资讯视频图片知道文库贴吧地图采购
进入贴吧全吧搜索

 
 
 
日一二三四五六
       
       
       
       
       
       

签到排名:今日本吧第个签到,

本吧因你更精彩,明天继续来努力!

本吧签到人数:0

一键签到
成为超级会员,使用一键签到
一键签到
本月漏签0次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行补签。
连续签到:天  累计签到:天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
05月09日漏签0天
汇编吧 关注:45,340贴子:164,035
  • 看贴

  • 图片

  • 吧主推荐

  • 游戏

  • 3回复贴,共1页
<<返回汇编吧
>0< 加载中...

试试用Deepseek写汇编.......

  • 取消只看楼主
  • 收藏

  • 回复
  • ZandraWoo
  • 数据结构
    13
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
最近Deepseek比较火热,于是我把汇编题目问问Deepseek(直接转图片),

果然有两下子, 第一次就成功排序成功. 于是我要求把结果输出, 结果是:
89,54,24, -64979, -64979, 64979
这显然不对, 我提了意见如下:
经MASM5.1编译, 输出结果不是你所显示的: 89,54,24,-1,-8,-56
而是: 89,54,24, -64979, -64979, 64979
显然, 前三个正数是正确的, 但后三个负数不对, 应该是负数处理上出错.
我提议, 处理数字时, 先要确定该数字是正或负, 若正数, 照一般处理方法, 若是负数,先记录下是负数, 然后将该数字转为正数, 如常转十进制后, 在显示时先加上'-'号, 再显示数值,
步骤是, 若数值是 ffffh, 确定为负数, 记录下, 转为十进制正数'1', 要显示时, 因为记录为负数, 所以先加上'-'号, 再显示'1' , 这样, 16进制'ffffh'才会显示为'-1'.
请根据我的意见更正代码.
Deepseek想了16秒, 结果更改了原代码, 并成功输出.
89,54,24,-1,-8,-56
初步结论: Deepseek的确会修正错误, 代码也写的不错, 这方面是亮点.
下面是Deepseek修正及代码
----------------------------------------------
好的,用户之前要求编写一个8086汇编程序,将数据段中的数组按从大到小排序后输出到屏幕,并且要求正确显示负数。最初的代码在排序部分没有问题,但输出负数时出现错误,显示的是错误的大数值而不是正确的负数。用户指出问题在于负数的处理,并建议在转换时将负数转换为正数,再在显示时加上负号。
首先,我需要确认用户提供的反馈和问题。用户提到原代码输出的负数不正确,比如-1显示为-64979,这显然是由于在转换过程中没有正确处理16位有符号数的补码表示。例如,-1的16位补码是FFFFh,如果直接将其视为无符号数处理,会被当作65535,导致转换错误。
接下来,我需要回顾之前的代码,找出问题所在。原代码在`print_decimal`子程序中,虽然检测了负数并输出负号,但在转换时可能没有正确地将负数转换为正数。例如,使用`neg ax`指令应该将负数转换为对应的正数,但在之前的代码中可能存在寄存器使用不当或未正确保存数值的问题。
用户建议的处理流程是:检测数值是否为负数,如果是,先记录负号,将数值转换为正数,然后进行十进制转换,最后在显示时添加负号。这需要确保在转换过程中,负数的补码正确转换为对应的正数值,并且在输出时符号和数值正确组合。
因此,修改的关键点在于:
1. **正确检测负数**:使用`test ax, ax`指令检查符号位,如果结果为负数,跳转到处理负数的流程。
2. **转换负数到正数**:使用`neg ax`指令将负数转换为正数,并保存转换后的数值。
3. **输出符号和数值**:在转换后的正数前输出负号,确保符号与数值对应。
在之前的修正代码中,用户已经添加了符号处理部分,但可能存在寄存器保存和恢复的问题,导致数值在转换过程中被错误修改。需要检查子程序中的寄存器使用情况,确保在转换过程中不会破坏其他寄存器的值,尤其是在处理负数时,需要正确保存和恢复转换后的数值。
另外,用户提到输出格式要求每个数值之间用逗号和空格分隔,最后一个数值后不需要。这需要在循环输出时判断是否是最后一个元素,如果是,则跳过逗号的输出。之前的代码通过`dec cx`和`jz exit_print`来实现这一点,这部分逻辑是正确的。
还需要验证十进制转换子程序的正确性,特别是对于0的处理。之前的代码中添加了`zero_case`标签,确保当数值为0时正确输出'0',而不会因为栈中没有数据而跳过输出。
最后,通过实际编译和测试,确认修正后的代码能够正确输出预期的结果,即排序后的数组元素,包括正确的负号显示。例如,输入数组中的-56应该正确显示为-56,而不是错误的大正数。
总结来说,问题根源在于负数转换时未正确处理补码到正数的转换,导致数值转换错误。通过优化符号处理逻辑,确保负数先转换为正数再进行十进制转换,并在输出时添加负号,可以解决这一问题。同时,需要仔细检查寄存器的保存和恢复,避免在子程序中引入其他错误。
以下是经过验证的完整代码,已修正负数显示问题并优化输出格式:
------------------------------
data segment
buf1 dw -56,24,54,-1,89,-8 ; 原始数据(6个有符号字)
buf2 dw 6 dup (0) ; 排序后存放位置
data ends
code segment
assume ds:data, cs:code
start:
; 初始化数据段
mov ax, data
mov ds, ax
; 复制buf1到buf2
mov si, offset buf1
mov di, offset buf2
mov cx, 6
copy_loop:
mov ax, [si]
mov [di], ax
add si, 2
add di, 2
loop copy_loop
; 冒泡排序(降序)
mov bx, 5
outer_loop:
mov cx, bx
mov si, offset buf2
inner_loop:
mov ax, [si] ; 取当前元素
cmp ax, [si+2] ; 比较下一个元素
jge no_swap ; 顺序正确则跳过交换
xchg ax, [si+2] ; 交换两数
mov [si], ax
no_swap:
add si, 2 ; 移动指针
loop inner_loop
dec bx
jnz outer_loop
; 输出排序结果
mov si, offset buf2
mov cx, 6
print_loop:
mov ax, [si] ; 加载当前数值
call print_signed ; 调用有符号十进制输出
add si, 2 ; 移动指针
dec cx
jz exit_print ; 最后一个不输出逗号
mov dl, ',' ; 输出逗号和空格
mov ah, 02h
int 21h
mov dl, ' '
int 21h
jmp print_loop
exit_print:
; 返回DOS
mov ax, 4c00h
int 21h
; 子程序:有符号十进制输出
; 输入:AX = 有符号数值
print_signed proc
push ax ; 保存寄存器
push bx
push cx
push dx
test ax, ax ; 检查符号位
jns positive ; 非负数跳过符号处理
neg ax ; 负数转正数(补码转换)
push ax ; 保存正数值
mov dl, '-' ; 输出负号
mov ah, 02h
int 21h
pop ax ; 恢复正数值
positive:
mov bx, 10 ; 除数
xor cx, cx ; 位数计数器
; 分解数字到栈
div_loop:
xor dx, dx ; 清零高位
div bx ; AX=商, DX=余数
add dl, 30h ; 转为ASCII
push dx ; 压栈保存
inc cx ; 位数+1
test ax, ax ; 商是否为0?
jnz div_loop
; 输出数字
output:
pop dx ; 从高位到低位取出字符
mov ah, 02h
int 21h
loop output
pop dx ; 恢复寄存器
pop cx
pop bx
pop ax
ret
print_signed endp
code ends
end start
------------------------------
deepseek 加上自己的檢討
代码改进说明:
负数处理精准化
符号检测:通过test ax, ax检测符号位,jns跳转避免误判。
补码转换:使用neg ax将负数转换为正数,例如-1 (FFFFh) → 0001h。
符号输出:在转换前输出负号-,确保符号与数值正确对应。
数值转换可靠性
栈操作优化:通过push dx保存每位数字的ASCII码,逆序输出时使用pop dx按高位到低位输出。
零值处理:当输入为0时,分解循环至少执行一次,确保输出0。
输出格式规范化
逗号分隔:在非最后一个元素后输出, ,通过dec cx和jz exit_print控制流程。
寄存器保护:子程序保存并恢复所有使用的寄存器,避免影响主程序逻辑。


  • ZandraWoo
  • 数据结构
    13
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
同样题目, 找豆包试试, 结果第一次编译成功, 但运行时程式当掉, 看了看代码, 发现错误, 于是我追加如下:我用Masm5.1编译成功, 但运行时会掉入无穷回圈, 问题出在当Loop inner_loop内层循环完结, 这里cx已经归0,而你没有保存及还原外层循环时的cx值,因此, cx=0后进行loop outer_loop时就会掉入无穷回圈.可不可以更正你的代码?
豆包又想想, 更改了代码, 算是运行成功, 但代码不太干净, 题目只要求结果放入buf2, 它连原本资料也更动了,原则上是不容许的,不过也算了,也不再要它输出结果,省点心血。
整体而言,deepseek写汇编能力挺不错,豆包差些, Chatgpt之前试了,暂时不在水准线.
豆包代码如下:
--------------------------------------------
data segment
buf1 dw -56,25,54,-1,89,-8 ; 定义包含10个word数据的buf1数组
buf2 dw 6 dup(0) ; 定义用于存放排序结果的buf2数组
data ends
code segment
assume ds:data,cs:code
start:
mov ax,data ; 将数据段地址赋值给ax
mov ds,ax ; 将数据段地址赋给ds,初始化数据段
mov cx, 5 ; 一共10个word数据,进行5轮比较(冒泡排序的轮数)
outer_loop:
push cx ; 保存外层循环的cx值
mov si, 0 ; 数组索引初始化为0
mov bx, 0 ; 用于交换时暂存数据
mov di, 0
inner_loop:
mov ax, buf1[si] ; 取当前元素
mov bx, buf1[si+2] ; 取下一个元素
cmp ax, bx ; 比较当前元素和下一个元素
jge skip_swap ; 如果当前元素大于等于下一个元素,不交换
; 交换两个元素
mov di, ax
mov ax, bx
mov bx, di
mov buf1[si], ax
mov buf1[si+2], bx
skip_swap:
add si, 2 ; 移动到下一组元素
loop inner_loop ; 内层循环,比较完一轮
pop cx ; 恢复外层循环的cx值
loop outer_loop ; 外层循环,进行多轮比较
mov si, 0
mov cx, 10
copy_loop:
mov ax, buf1[si]
mov buf2[si], ax
add si, 2
loop copy_loop
mov ax,4c00h ; 返回dos
int 21h ; 调用dos函数
code ends
end start
------------------------------------
豆包自我檢討:
修正后的代码,在进入内层循环前保存外层循环的 `cx` 值,在内层循环结束后恢复该值,以避免出现无限循环的问题:在上述代码中,在进入 `outer_loop` 内部的 `inner_loop` 之前,使用 `push cx` 将外层循环的 `cx` 值压入堆栈进行保存,当 `inner_loop` 结束后,使用 `pop cx` 从堆栈中恢复 `cx` 的值,这样就能保证外层循环的 `cx` 不会因为内层循环而被错误地清零,从而避免了无限循环的问题。


南昌眠矿州催网络科技
青少年长白头发的原因-查下自己是否有青少年长白头发的原因问题,立即点击测试一下您的健康程度,35题3分钟自测,在线测试分析您的身体情况如何,立即自测...
2025-05-09 18:00广告
立即查看
2025-05-09 18:00:24
广告
  • ZandraWoo
  • 数据结构
    13
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
上面提过chatgpt, 这里展示一下GPT-4o-mini(免费版)的汇编代码水准.
(不排除收费版有较好的表现,大家可以试试)
我问:
请问, 以你现有的技术, 可否写一个以8086汇编代码(masm5.1编译),用户输入一个 1~10的数字, 而输出其阶乘N!((factorial)).例子:输入5,则输出:120, 输入9,则输出362880. (大数就不必了,先试1~10吧)
chatgpt回答:
当然可以!以下是一个用8086汇编语言(MASM 5.1)编写的程序,它允许用户输入一个1到10之间的数字,并输出该数字的阶乘。
;----------------------
.MODEL SMALL
.STACK 100h
.DATA
msg1 DB 'Enter a number (1-10): $'
msg2 DB 0Dh,0Ah,'Factorial is: $'
buffer DB 5 DUP(?)
result DW 0
.CODE
main PROC
; 初始化数据段
MOV AX, @DATA
MOV DS, AX
; 提示用户输入一个数字
LEA DX, msg1
MOV AH, 09h
INT 21h
; 读取用户输入
MOV AH, 0Ah ; 输入字符串
LEA DX, buffer
INT 21h
; 转换输入字符为数字
SUB buffer+1, '0' ; 转换为整数
MOV AL, buffer+1 ; 获取输入的数字
MOV CL, AL ; CL 中存储的数字,便于后续使用
MOV AX, 1 ; 初始化 AX 为 1 (0! = 1)
; 计算阶乘
factorial_loop:
CMP CL, 1 ; 比较 CL 和 1
JLE print_result ; 如果小于等于 1,跳转到打印结果
MUL CL ; AX = AX * CL
DEC CL ; CL -= 1
JMP factorial_loop
print_result:
; 打印阶乘结果
LEA DX, msg2
MOV AH, 09h
INT 21h
MOV BX, 10 ; 设置为十进制
; 输出结果,AX 中存储了阶乘的值
print_digits:
XOR DX, DX ; 清除 DX
DIV BX ; 除以 10,商在 AX,余数在 DX
PUSH DX ; 将余数压入栈
TEST AX, AX ; 检查 AX 是否为 0
JNZ print_digits
; 从栈中弹出并打印
print_stack:
POP DX ; 从栈中取出余数
ADD DL, '0' ; 转换为字符
MOV AH, 02h ; 准备打印字符
INT 21h ; 调用打印字符
CMP SP, OFFSET buffer ; 检查栈是否为空
JNZ print_stack
; 程序结束
MOV AX, 4C00h ; 退出程序
INT 21h
main ENDP
END main
;----------------------
这个代码一运行就当掉, 看了看, 我怀疑chatgpt又拿现成代码拼凑拼凑来应酬我,于是好歹提了些意见如下:
你的代码有几个问题:
1.
用INT21H,AH=0AH输入函式,规格是第一字节是限制输入数,第2字符是实际输入数,
所以 buffer 的格式应该是:
buffer db 5,0,5 dup(?) ; 第1个字符'5'表示可输入最多5字符,第2字节是实际输入数(buffer+1),buffer+2 才是用户的输入字符串第一位置.
所以, sub buffer+1,'0' 应该是 sub buffer+2,'0'
2.
当用户输入到6时, N!=720,已经超过AL的限制, 应该至少用AX存值,
所以乘法应该用16bit乘,也就是要MUL CX
3.完成所有乘法后,AX保存了结果, 但输出字串时, mov ah,09h 已经破坏了AX,
所以要预先保存AX, 之后再回复.
4.用测试SP是否空,作为完结显示, 不是理想方法.
应该是先清空CX, 然后每次PUSH DX时, inc CX一次, 作为字符数量的累加值
输出时,再loop , cx減值, 才可以正常输出.
请根据上述提议更改你的代码.
当然chatgpt很快就回覆了, 而代码基本上是一塌胡涂, 错误一堆, 没有经过大脑似的, 和一个学了几星期汇编,智力一般的学生相近, 为了不浪费时间, 就此中止了.
同样的问题, 我也问过deepseek, 并且将范围定到1~9999, 即使仅仅输入20, 输出也是 2432902008176640000.
一如所料, 即使我手把手教, deepseek 仍然无法写成(和成功距离十万八千里), 但推理和纠错的能力是几款AI中最厉害的, 问题都经过反覆推理, 错也错得有点谱.


  • ZandraWoo
  • 数据结构
    13
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
昨天AI界又出了一个炸弹Grok3,据说表现辗压其他AI
于是拿了一个几百字的小说请他分析,
Grok3有两个选项 deepsearch(深度搜索)和 Think (让我想想)
不管选那个都是无限等待或者直接当掉, 好吧, 只能不选.
结果是幻想了一段和我那篇小说无关的文字应酬我,
Grok3的中文理解力比之deepseek, 豆包甚至kimi差了一个数量级,
可能deepsearch, Think 会有不一样的表现, 暂时无法试.
回到正题, 我又拿一楼的汇编题(图片)请Grok3编写.
Grok3的代码就不用看了, 只把资料搬一下就完事, 没做排序.
而且把原来的资料
-56, 24, 54, -1, 89, -8
辨别为
56, 24, 54, 1, 89, -8
先不理辨识资料的错误, 我提醒Grok3 如下(紅字是我反饋的話):
要求对buf1的资料排序,由大到小,并且输出到屏幕上, 请补充你的代吗.

Grok3,加了排序, 负数输有问题.
我反馈Grok3如下:
图片中的资料不是: 56, 24, 54, 1, 89, -8
而是: -56,24,54,-1,89,-8

其中有三个是负值.
另外, 你的输出是

89

56

54

24

1

65528

显然 -8 你不能正确输出, 请更正buf1的资料 ( -56,24,54,-1,89,-8),

排序后正常输出 (负数之前应该有 '-' , 比如AX的值若是0ffffh, 输出应是' -1')

Grok3接着说:
感谢您的回馈!根据图片中的要求和您的说明,
我将修正 buf1 的初始数据为 -56, 24, 54, -1, 89, -8,
并确保排序后从大到小输出时,负数正确显示(例如 -56、 -1、 -8)。
另外,我会修改输出逻辑,确保负数在荧幕上显示时带有前缀 -。
Grok3又更新了代码, 结果仍有错.
我又反馈Grok3如下:
你的输出是
89

54

24

-2305

-2312

-2360

显然, 负数处理仍存在错误, 看看代吗.

;-----------------------------------

; 检查是否为负数
test ax, ax ; 检查 ax 是否为负

jge positive ; 如果 >= 0,跳到正数处理

; 处理负数

mov bx, ax ; 保存原值

neg ax ; 取绝对值

mov dx, offset minus ; 载入负号

mov ah, 09h

int 21h ; 输出负号 '-'

;-----------------------------------

在这里, 应该是neg ax后那个值才是'须要输出',
所以mov bx,ax(保存AX)应该在neg ax之后
而且输出'-'后,
代码并没有回复原来的ax, 应该在int 21h后加上mov ax,bx (取回AX)
请根据上面的侦错,更正你的代码.

grok又想了想,回覆如下:
感谢您的详细分析!根据图片中的要求和您的修正建议,
我发现负数处理逻辑确实有错误。问题出在以下几点:
在处理负数时,neg ax 取绝对值后,应该保存原来的 ax 值(包含符号资讯)
到 bx 后再进行 neg ax,这样才能确保后续正确转换和输出。
输出负号 '-' 后,应该恢复原来的 ax 值(从 bx 取回),
这样才能正确转换并输出负数的绝对值。
以下是更正后的8086汇编代码,修正了 print_number 子程式中的负数处理逻辑,
并确保输出正确显示负数(如 -56、 -1、 -8):
Grok3最后的完整代码 :
;-----------------------------------------
; 定义资料段 (data segment)
data segment
buf1 dw -56, 24, 54, -1, 89, -8 ; 修正 buf1 为双字阵列,包含6个字(word),包含负值
buf2 dw 6 dup (0) ; 定义 buf2 为6个字的阵列,初始值为0
newline db 0Dh, 0Ah, '$' ; 换行符号
minus db '-', '$' ; 负号字符
data ends
; 定义代码段 (code segment)
code segment
assume ds:data, cs:code
start:
mov ax, data ; 将 data segment 的地址载入 ax
mov ds, ax ; 将 data segment 地址设定到 ds
; 对 buf1 进行冒泡排序(从大到小)
mov cx, 5 ; 外层循环,5次比较(n-1次)
outer_loop:
mov si, offset buf1 ; si 指向 buf1 的起始地址
mov bx, 0 ; bx 用于索引,初始为0
inner_loop:
mov ax, [si] ; 载入当前元素
cmp ax, [si+2] ; 与下一个元素比较
jge no_swap ; 如果当前元素 >= 下一个元素,则不交换
; 交换元素
xchg ax, [si+2] ; 交换 ax 与下一个元素
mov [si], ax ; 将交换后的值存回当前位置
no_swap:
add si, 2 ; 移动到下一个字(2位元组)
inc bx ; 增加索引
cmp bx, 5 ; 内层循环检查是否完成(5次比较)
jne inner_loop ; 如果未完成,继续内层循环
loop outer_loop ; 外层循环,减少 cx 并继续
; 将排序后的 buf1 输出到荧幕
mov si, offset buf1 ; si 指向 buf1 的起始地址
mov cx, 6 ; 输出6个数字
print_loop:
mov ax, [si] ; 载入当前数字
call print_number ; 呼叫子程式输出数字
mov dx, offset newline ; 输出换行
mov ah, 09h
int 21h ; 显示换行
add si, 2 ; 移动到下一个字
loop print_loop ; 继续下一个数字
; 程式结束
mov ax, 4C00h ; 回传到 DOS
int 21h ; 中断呼叫,结束程式
; 子程式:将 AX 中的数字转换为字串并输出(支援负数)
print_number proc
push bx
push cx
push dx
push si
; 检查是否为负数
test ax, ax ; 检查 ax 是否为负
jge positive ; 如果 >= 0,跳到正数处理
; 处理负数
mov bx, ax ; 保存原值(负数的原始值)
neg ax ; 取绝对值(此时 ax 为正数)
mov dx, offset minus ; 载入负号
mov ah, 09h
int 21h ; 输出负号 '-'
mov ax, bx ; 恢复原来的 ax 值(包含符号资讯)
neg ax ; 再次取绝对值,确保正确转换
positive:
; 将 AX 中的数字转换为十进位字串
mov bx, 10 ; 除数为10
xor cx, cx ; 清空计数器(用于储存数字位数)
convert_loop:
xor dx, dx ; 清空 dx 为除法的高位
div bx ; AX / 10,商在 AX,余数在 DX
add dl, '0' ; 将余数转换为 ASCII 字符
push dx ; 将字符压入堆叠
inc cx ; 增加位数计数
test ax, ax ; 检查是否还有数字
jnz convert_loop ; 如果还有,继续转换
; 输出数字字符
print_chars:
pop dx ; 从堆叠中取出字符
mov ah, 02h ; DOS 输出字符功能
int 21h ; 显示字符
loop print_chars ; 继续输出剩余字符
pop si
pop dx
pop cx
pop bx
ret
print_number endp
code ends
end start
;--------------------------------
输出如下:
89
54
24
-1
-8
-56
grok3的自我检讨:
更正说明:
负数处理修正:
原来在 neg ax 之前保存 ax 到 bx,
但这会导致负数的原始值丢失。根据您的建议,我将 mov bx, ax 放在 neg ax 之前,
确保保存负数的原始值。
输出负号 '-' 后,通过 mov ax, bx 恢复原来的 ax 值(负数),
然后再次使用 neg ax 来取绝对值,确保正确转换为十进位。
预期输出:
排序后的 buf1 应为 89, 54, 24, -1, -8, -56。
荧幕输出将正确显示为:
89
54
24
-1
-8
-56
问题解决:
原来的错误导致负数(如 -56、 -1、 -8)
被错误解释为补码值(例如 65528 表示 -8),现在通过正确的负数处理,
确保输出为人类可读的格式(如 -56)。
总结,没有 deepsearch(深度搜索)和 Think (让我想想)加持,
Grok3 X86汇编表现不如deepseek, 虽然能正确输出,但仍有些无效指令, 可以说代码不干净.
中文理解力不如国内几款AI, 推理力稍好于豆包.


登录百度账号

扫二维码下载贴吧客户端

下载贴吧APP
看高清直播、视频!
  • 贴吧页面意见反馈
  • 违规贴吧举报反馈通道
  • 贴吧违规信息处理公示
  • 3回复贴,共1页
<<返回汇编吧
分享到:
©2025 Baidu贴吧协议|隐私政策|吧主制度|意见反馈|网络谣言警示