汇编语言第五章(loop)
编程时应该注意什么?
数据来源 寄存器、内存地址 访问方式: ds:[0] 或ds:[bx]
数据的长度: 字节、字
数据的归宿: es
需要记住返回指令:
mov ax, 4c00h
int 21h
ps:int 指令需要 用 -p 执行
现在 来思考一下 2^N 如和计算
嗯,之前写过 2^3是,酱紫的:
mov ax, 2 add ax, ax add ax, ax
那么,理论上 2 的n次方 就是, 酱紫的
assume cs:code code segment start: mov ax, 2 add ax, ax add ax, ax add ax, ax add ax, ax add ax, ax add ax, ax add ax, ax add ax, ax add ax, ax add ax, ax ... ;执行n次 mov ax, 4c00h int 21h code ends end start
一点通用性都没有🐎,而且, 不考虑寄存器的限制时 100w 次方我就得写至少
100w+1行……,
所以我们来思考一下如和化简?
嗯,机智如我,嘿嘿!jmp, 可以往回跳 嘿嘿 所以我的代码就成这样了,
等等, 往哪跳?嗯,是个问题,当初学的 jmp,是跳到一个固定的
地址,我这个程序,每一次运行地址不会固定啊。赶忙去调戏了一波度娘
发现jmp 得这样用:
setNumber: ;要jmp的位置
;中间代码
jmp setNumber
嗯,当当当当,新的代码:
assume cs:code code segment start: mov ax, 2 setNumber: add ax, ax jmp setNumber mov ax, 4c00h int 21h code ends end start
绝妙啊,等等,停不下来了,你是嚼了炫迈吗
得再调教一下,寄存器小姐姐拷问划开始……
嗯,经过一波 灵魂拷问, 寄存器小姐姐终于屈服了,招出了幕后元凶——迭代器!
这下,不行了,莫得办法了,只能祭大招了 决定就是你了——loop
循环指令:loop
终于等来了超级简化大法!!!
结构:
s: ;代码
loop s
ps:cx 决定循环次数
代码就变成这样了:
assume cs:code code segment start: mov ax, 2 mov cx, 3 s: add ax, ax loop s mov ax, 4c00h int 21h code ends end start
打完,收工
这里有一道脑筋转弯,马上就可以鉴别你是不是一个汇编程序员
用编程进行加法运算 123 * 456,请问如何优化(只能用加法)?
说出你的想法~
无比机智的我第一反应就是,把每次相加的结果存储起来,再相加,类似于 2^16次方
先算 2+2, 再算 4+4, 然后算 8+8,这样只计算次数就可以缩减到 log级, 等等
对数……,对数怎么算啊,凉凉,莫得戏
转念选项 123 * 456 就是 123 加 456 次,
123*456 == 456 * 123,
哎~,成了, 把 456 计算 123 次,真的少了不少
2^100w 少的更多...
真的是机智如我啊
后面就是枯燥的编程题了:我咬发森为莫得情感的刷题机器人
1、将内存 FFFF:0 ~ FFFF:F 内存中单元数据赋值到 0:200 ~ 0:20F中
我莫得感情:
assume cs:code code segment start: mov ax, 0ffffH ;数字不允许以字母开头 mov ds, ax ;设置数据从哪来 mov ax, 20H mov es, ax; ;设置数据到哪去 mov bx, 0 mov cs, 8 ;初始化 setNumber: mov dx, ds:[bx] mov es:[bx], dx add bx, 2 loop setNumber mov ax, 4c00h int 21h code ends end start
我觉得我已经狗机制了比一个个字节移动快了一倍,大佬更狗
assume cs:code code segment start: mov ax, 0ffffH ;数字不允许以字母开头 mov ds, ax ;设置数据从哪来 mov ax, 20H mov es, ax; ;设置数据到哪去 mov bx, 0 mov cx, 8 ;初始化 setNumber: push ds:[bx] pop es:[bx] add bx, 2 loop setNumber mov ax, 4c00h int 21h code ends end start
寄存器都省了,临时保存,随时释放.......是在下输了
2. 向内存中 0:200 ~ 0:23F 依次传递 数据 0 ~ 63(3FH),程序中只允许有9条指令
莫得感情的我:(想不出来)
assume cs:code code segment start: mov ax, 20H ;数字不允许以字母开头 mov es, ax ;设置数据从哪来 mov bx, 0 mov cx, 64 mov dl, 0 ;初始化 setNumber: mov es:[bx], dl inc dl inc bx, 2 loop setNumber mov ax, 4c00h int 21h code ends end start
更加莫得感情的大佬:
assume cs:code code segment start: mov ax, 20H ;数字不允许以字母开头 mov es, ax ;设置数据从哪来 mov bx, 0 mov cx, 64 ;初始化 setNumber: mov es:[bx], bl inc bx loop setNumber mov ax, 4c00h int 21h code ends end start
但是,老师更加喜欢我这种代码
总结:今天肯定不止敲了2000次 t 和 回车键,没啥好总结的了,该说的都说了
我还写了一个 从 2~N 的 平方的代码,当然溢出我就没办法了(我用了一点第六章的东西)
assume cs:code, ss:stack, ds:data data segment dw 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ;这里的数据可以自行替换 data ends stack segment dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;这里是栈的初始化和大小 stack ends code segment start: mov ax, stack mov ss, ax mov sp, 20h ;设置栈定 ss:sp 指向 stack:20 mov ax, data mov ds, ax ;数据段设置 mov bx, 5*2 ;设置平方的底数 mov ax, [bx] mov cx, [bx] dec cx ;设置循环次数,0 ~ n-1 s: add ax, [bx] loop s ;循环的主体,执行完这一句就等于完成了n^2的计算 push ax pop dx ;栈测试 mov ax, 4c00h int 21h code ends end start