包头哪有做网站的,中国品牌网站,网站漏洞,想开发自己的网站文章目录 随笔Bug1、masm编译报错#xff1a;Illegal use of register2、debug中使用段前缀3、[idata]在编译器中的处理4、push立即数报错5、报错#xff1a;improper operand type6、程序莫名跳转到未知位置 (doing)7、DOSBox失去响应8、程序运行显示乱码9、程序运行导致DOS… 文章目录 随笔Bug1、masm编译报错Illegal use of register2、debug中使用段前缀3、[idata]在编译器中的处理4、push立即数报错5、报错improper operand type6、程序莫名跳转到未知位置 (doing)7、DOSBox失去响应8、程序运行显示乱码9、程序运行导致DOSBox窗口自动关闭10、如何换行输出11、公司收入项仅输出了一行12、loop指令报错jump out of range by 7 byte(s)13、忘记程序返回14、开始解析的位置不同代码也不同15、中断例程安装与子程序调用 问题想法 随笔 与汇编的灵活与底层所伴随的是使用者极大的心智负担。 模块之间的隔离性很难控制。甚至多个子程序间的标号也不能相同故子程序无法独立开发后直接集成。 cx是个高频冲突寄存器呢 程序过度的复杂性往往令我感到沮丧无力。多层的子程序、循环嵌套也让程序的调试变得十分困难甚至折磨而此时我缺乏一个有效的调试工具。 寄存器的冲突、覆盖真是频繁又隐晦的bug产生令人摸不着头脑的效果。 2023-10-21 关于《汇编语言》作者王爽的学习就此告一段落了最后一章第17章还剩一个实验和一个课程设计。但磁盘读写好像在DOSBox中没用做不了。此外还有一个“综合研究”部分有空倒可以看看。这本书一共差不多花了40~50个小时吧我阅读并验证了书中的大部分代码做了书中的每一个实验除了最后一章的还算是有不少收获吧。能比较完整地啃下来一本书也挺有成就感的同时也能为日后的学习增添点自信心。 Bug
1、masm编译报错Illegal use of register
mov es:bp.0[0]报错的意思是非法使用寄存器。代码应修改如下
mov es:[bp].0[0]2、debug中使用段前缀
在代码中可以这样写
mov ax, es:[bx]但在debug中不能直接这样写要分两行
es:
mov ax,[bx]3、[idata]在编译器中的处理
在debug模式中可以直接使用[idata]的写法如
mov ax,[6]但如果是写在文件里要用编译器编译运行的不能使用立即数应当使用寄存器中转一下。
mov bx,6
mov ax,[bx]4、push立即数报错
push 02h会出现错误信息Immediate mode illegal。应先将立即数放入寄存器然后push寄存器。
mov ax,02h
push ax5、报错improper operand type
mov byte ptr es:[bxdi], [si]其实是犯了一个老错误mov不能直接将一个内存单元中的数据移动到另一个内存单元而需要通过寄存器。因为cl是8位指明了目标数据的尺寸就不必使用byte ptr指明数据的尺寸。
mov cl, [si]
mov es:[bxdi], cl6、程序莫名跳转到未知位置 (doing) 图中在执行完命令div cx后下一条指令迷路了。初步猜测是使用栈却未初始化sp与debug程序对栈的借用导致的联动bug但暂未仔细分析。完整代码如下
assume cs:code code segment
start:mov ax,4240hmov dx,000fhmov cx,0ah call divdw mov ax,4c00hint 21h;功能进行不会溢出的除法运算除数为word型被除数、结果为dword型
;参数(ax)被除数的第6位, (dx)被除数的高6位, (cx)除数
;返回(dx)结果的高16位, (ax)结果的低16位, (cx)余数
divdw:push dx push ax mov bp,sp mov ax,[bp2] div cx push ax mov ax,[bp]div cx mov cx,dx ;保存余数pop dxret
code ends end start7、DOSBox失去响应
在运行自己编写的汇编程序后DOSBox虚拟机就失去响应了。
员工数据段长度错误。再次出现问题6程序莫名跳到未知位置。
分析在执行命令mov bx,[di00ab]后寄存器bx的值变为了0随后导致div bx命令发生除0错误。因为员工数中少了一个数据下一个数据被后面定义的0所覆盖自然bx也变成了0。 为什么上次单独运行表格结构化程序没有发现问题 答那时后面没有紧接着定义一些0数据可能后面的数据刚好不是0。虽然数据不对但程序照常执行。待核定 8、程序运行显示乱码
原因我在用于显示字符串的show_str子程序中利用es寄存器存放目标显存的地址。而在主程序中es本来是指向存放表格数据的数据段于是导致了冲突数据乱了。
总而言之是子程序的隔离性没有做好。可以在子程序开始时将es寄存器入栈保护现场返回前再出栈恢复。 9、程序运行导致DOSBox窗口自动关闭 这bug真的是越修越离谱。运行程序k1随后在指定的地方成功显示出绿色的1975字样但在几秒的延迟后窗口直接关闭了。 下面是我显示字符串的子程序。可以看到使用了栈的命令包括
push es
push cx
pop cx
pop es看起来好像收支平衡对栈的使用是正常的。然而在结束循环时的jcxz ok命令却会直接跳过一次pop cx。这下问题就大了后面的pop es将会把原来cx寄存器的内容写入到es段寄存器中然后发生一些不为人知的事情很可能就导致了程序的崩溃。
一个很容易想到的方法是在pop es前添上一个pop cx弥补这个过错。
; 6 子程序 - 显示字符串
;说明显示一个以0结尾的字符串在第y行第x列颜色为color字符串起始位置为local
;参数(dh)y, (dl)x, (cl)color, ds:silocal
show_str:push es ;避免与主程序冲突;绑定显存段mov ax,0b800hmov es,ax ;定位行mov al,0a0h mul dh mov bx,ax ;定位起始列dec dladd dl,dl mov dh,0mov di,dx ;通用寄存器初始化mov ch,0s_show:;判断结尾push cx mov cl,[si] jcxz ok;写入一个字符及其属性mov byte ptr es:[bxdi], cl pop cx mov es:[bxdi1], cl ;循环迭代inc si add di,2jmp s_show;程序返回ok: pop esret10、如何换行输出 我本来的想法是在待输出的字符串中添加换行符期待在输出的时候就会自动换行但效果如下。 这才突然想到我是通过直接向显存中写入数据来输出字符的。这种方法并不会奏效。
11、公司收入项仅输出了一行
年份是正常输出了但收入一栏却仅输出了一行。猜测有两种可能
输出坐标出错所有收入都写在一行覆盖了。字符串早前就未正常写入待显示区。
我调整了循环次数收入仍然仅输出一行数字却发生了改变变成了前一个数字故大概率是第一种情况。 12、loop指令报错jump out of range by 7 byte(s) 意思是循环体的长度超出了loop指令的最大范围超出量为7个字节注意一条指令通常并不是仅一个字节。 由此我产生了两种想法
使用我突发奇想的二级跳从loop先跳到中间一个标签s0再经过某种验证刚刚是从后面的loop跳过来的而不是从前面执行过来的后跳到循环开始的标签s处。将一些重复度较高的指令封装为子程序减少循环中显示的指令条数。
最后我都失败了程序出现了莫名其妙的bug未能解决。
13、忘记程序返回 代码的逻辑检查了好几遍硬是感觉毫无bug。可在正常输出的时间信息后面还输出了一团乱七八糟的字符并将DOSBox成功卡死。 最后发现原来是忘了程序返回也不知道怎么就导致了那一团东西出现在屏幕上。
mov ax,4c00h
int 21h14、开始解析的位置不同代码也不同 从0000:0200开始的第一行汇编代码是jmp 020A可顺着往下看发现根本就没有从020A开头的代码。不过如果直接从020A开始查看同样的内存区间看到的又是另外一套代码。 15、中断例程安装与子程序调用 有一个利用了直接定址表编写的多功能子程序我要将它安装成中断例程并使用然而原本正常的程序却突然爆出bug。我步步为营仔细地推断、分析后总算还是让它正常跑起来了。最初的问题代码已在下面列出。 其实最后回头一看也就是几个小问题可我真的找了好久才成功发现它们。
;安装中断例程7ch -- 200h
;bug版assume cs:code code segment
start:;拷贝例程代码mov ax,cs mov ds,ax mov ax,0mov es,ax mov si,offset setscreen ;ds:si源地址 mov di,200h ;es:di目的地址 mov cx,offset setscreenend-offset setscreencld rep movsb;设置中断向量表mov ax,0 mov es,ax mov word ptr es:[7ch*4], 200h ;例程偏移地址mov word ptr es:[7ch*42], 0 ;段地址mov ax,4c00h int 21h;参数(ah)功能号
;说明0清屏, 1设置前景色, 2设置背景色, 3向上滚动一行
setscreen:jmp short set table dw sub1,sub2,sub3,sub4set:push bx cmp ah,3 ja sret mov bl,ah mov bh,0 add bx,bx ;根据功能号计算在table中的偏移call word ptr table[bx]sret:pop bx retsub1:push bx push cx push es mov bx,0b800hmov es,bx mov bx,0 mov cx,2000sub1s:mov byte ptr es:[bx], add bx,2 loop sub1s pop es pop cx pop bx ret sub2:push bx push cx push es mov bx,0b800hmov es,bx mov bx,1 mov cx,2000 sub2s:and byte ptr es:[bx],11111000b or es:[bx],al add bx,2 loop sub2s pop espop cx pop bx ret sub3:push bx push cx push es mov cl,4 shl al,cl mov bx,0b800h mov es,bx mov bx,1 mov cx,2000 sub3s:and byte ptr es:[bx],10001111b or es:[bx],al add bx,2 loop sub3s pop es pop cx pop bx ret sub4:push cx push si push di push es push ds mov si,0b800h mov es,si mov ds,si mov si,160 mov di,0 cld mov cx,24 sub4s:push cx mov cx,160 rep movsb pop cx loop sub4s mov cx,80 mov si,0 sub4s1:mov byte ptr [160*24si], add si,2 loop sub4s1 pop ds pop es pop di pop si pop cx ret
setscreenend:nopcode ends
end start 问题
10_s10_1.asm运行效果有些奇怪第一行会多出同样的字符串并在短暂延迟后上移消失。而我之前做过的显示程序都没有出现这样的现象如10_t5.asm。如果子程序想要使用数据段内存可不知道父程序是否会使用如何避免冲突
想法
masm编译得到的.exe文件无法直接在我电脑上点击运行。我可以写一个脚本自动打开DBox虚拟机并在其中运行相应的程序吗写一个打字游戏