LEA 与 MOV 的区分

本文通过具体实例对比了MOV和LEA两条汇编指令的功能差异:MOV用于将指定内存位置的数据加载到寄存器中;而LEA则用于计算内存地址,并将该地址加载到寄存器。

这两个指令常被混淆, 举例说明:

MOV  DWORD PTR [EDI+EAX+28] , 0X10

MOV EAX, DWORD PTR [EDI+EAX+28] //将内存地址为EDI+EAX+28的4字节内容送到EAX中(执行后, EAX中的值是0X10) 

LEA EAX, DWORD PTR [EDI+EAX+28]  //取 DWORD PTR [EDI+EAX+28] 的地址送到EAX中, 即将地址EDI+EAX+28送到EAX中(执行后, EAX中的值是EDI+EAX+28)

 

转载于:https://www.cnblogs.com/goalpower/p/4051309.html

; 电子秒表程序 - MASM实现 ; 功能: 显示秒毫秒(1-60秒),支持开始/暂停/复位/退出 .MODEL SMALL .STACK 100h .DATA ; 时间变量 start_time DW 0, 0 ; 开始时间的时钟计数(高位:低位) current_time DW 0, 0 ; 当前时间的时钟计数 paused_duration DW 0, 0 ; 暂停期间的时间累计 paused DB 0 ; 暂停状态(0=运行,1=暂停) ; 显示变量 seconds DW 0 ; 秒数 milliseconds DW 0 ; 毫秒数 time_string DB '00:000', '$' ; 时间显示字符串 ; 提示信息 initial_msg DB 'Electronic Stopwatch (MASM)', 0Dh, 0Ah DB 'Press:', 0Dh, 0Ah DB 'S - Start/Pause', 0Dh, 0Ah DB 'R - Reset', 0Dh, 0Ah DB 'Q - Quit', 0Dh, 0Ah, '$' running_msg DB 'Running...', 0Dh, 0Ah, '$' paused_msg DB 'Paused. Press S to continue.', 0Dh, 0Ah, '$' .CODE MAIN PROC MOV AX, @DATA MOV DS, AX ; 初始化显示 CALL init_proc ; 主循环 main_loop: ; 检查键盘输入 CALL check_keyboard ; 如果暂停则跳过时间更新 CMP paused, 1 JE main_loop ; 获取当前时间 MOV AH, 00h INT 1Ah MOV current_time[0], DX MOV current_time[2], CX ; 计算时间差 CALL calculate_time ; 更新显示 CALL update_display ; 延迟以避免闪烁 MOV CX, 01h MOV DX, 0FFFFh MOV AH, 86h INT 15h JMP main_loop ; 退出程序 exit_program: MOV AX, 4C00h INT 21h MAIN ENDP ; 初始化过程 init_proc PROC ; 清屏 MOV AX, 0600h MOV BH, 07h MOV CX, 0000h MOV DX, 184Fh INT 10h ; 设置光标位置(显示提示信息) MOV AH, 02h MOV BH, 00h MOV DH, 10 ; 行 MOV DL, 25 ; 列 INT 10h ; 显示初始信息 LEA DX, initial_msg MOV AH, 09h INT 21h ; 设置光标位置(显示时间) MOV AH, 02h MOV BH, 00h MOV DH, 12 ; 行 MOV DL, 35 ; 列 INT 10h ; 显示初始时间 MOV seconds, 0 MOV milliseconds, 0 CALL update_display RET init_proc ENDP ; 检查键盘输入 check_keyboard PROC MOV AH, 01h ; 检查键盘状态 INT 16h JZ no_key ; 无按键则返回 MOV AH, 00h ; 读取按键 INT 16h CMP AL, 'S' ; 暂停/继续 JE toggle_pause CMP AL, 's' JE toggle_pause CMP AL, 'R' ; 复位 JE reset_timer CMP AL, 'r' JE reset_timer CMP AL, 'Q' ; 退出 JE exit_program CMP AL, 'q' JE exit_program no_key: RET toggle_pause: CMP paused, 1 JE unpause ; 暂停计时 MOV paused, 1 ; 记录暂停开始时间 MOV AH, 00h INT 1Ah MOV paused_duration[0], DX MOV paused_duration[2], CX ; 显示暂停信息 MOV AH, 02h MOV BH, 00h MOV DH, 14 ; 行 MOV DL, 25 ; 列 INT 10h LEA DX, paused_msg MOV AH, 09h INT 21h RET unpause: ; 继续计时 MOV paused, 0 ; 计算暂停持续时间并累加到paused_duration MOV AH, 00h INT 1Ah SUB DX, paused_duration[0] SBB CX, paused_duration[2] ADD paused_duration[0], DX ADC paused_duration[2], CX ; 清除暂停信息 MOV AX, 0600h MOV BH, 07h MOV CX, 0E00h MOV DX, 0E4Fh INT 10h RET reset_timer: ; 复位计时器 MOV seconds, 0 MOV milliseconds, 0 ; 重置开始时间 MOV AH, 00h INT 1Ah MOV start_time[0], DX MOV start_time[2], CX ; 重置暂停持续时间 MOV paused_duration[0], 0 MOV paused_duration[2], 0 ; 更新显示 CALL update_display RET exit_program: ; 退出程序(通过主程序中的跳转实现) RET check_keyboard ENDP ; 计算时间差 calculate_time PROC ; 计算当前时间开始时间的差值 MOV AX, current_time[0] SUB AX, start_time[0] MOV DX, current_time[2] SBB DX, start_time[2] ; 减去暂停期间的时间 SUB AX, paused_duration[0] SBB DX, paused_duration[2] ; 转换为秒毫秒 ; 时钟计数每秒约18.2次(每个计数约55ms) ; 计算秒数 (DX:AX / 18.2) ; 近似计算: 18.2 ≈ 182/10 ; 所以 count / 18.2 ≈ count * 10 / 182 ; 保存原始计数 PUSH DX PUSH AX ; 计算 count * 10 MOV BX, 10 MUL BX ; AX = low * 10 MOV CX, DX ; 保存高位结果 MOV DX, AX ; DX = low * 10 POP AX ; 恢复原始AX POP BX ; 原始DX在BX中 PUSH DX ; 保存低位结果 MOV AX, BX ; AX = 原始DX MOV BX, 10 MUL BX ; AX = high * 10 POP DX ; 恢复低位结果 ADD DX, AX ; DX:AX = count * 10 ; 现在除以182得到秒数 MOV BX, 182 DIV BX ; AX = 秒数, DX = 余数 ; 确保不超过60秒 CMP AX, 60 JLE store_seconds MOV AX, 60 store_seconds: MOV seconds, AX ; 计算毫秒数: 余数 * 1000 / 182 MOV AX, DX ; 余数 MOV BX, 1000 MUL BX ; DX:AX = 余数 * 1000 MOV BX, 182 DIV BX ; AX = 毫秒数 MOV milliseconds, AX RET calculate_time ENDP ; 更新显示 update_display PROC ; 转换秒数为ASCII MOV AX, seconds MOV BX, 10 XOR DX, DX DIV BX ; AX = 十位, DX = 个位 ADD AL, '0' MOV time_string[0], AL ADD DL, '0' MOV time_string[1], DL ; 转换毫秒数为ASCII MOV AX, milliseconds MOV BX, 100 XOR DX, DX DIV BX ; AX = 百位, DX = 余数 ADD AL, '0' MOV time_string[3], AL MOV AX, DX MOV BX, 10 XOR DX, DX DIV BX ; AX = 十位, DX = 个位 ADD AL, '0' MOV time_string[4], AL ADD DL, '0' MOV time_string[5], DL ; 设置光标位置 MOV AH, 02h MOV BH, 00h MOV DH, 12 ; 行 MOV DL, 35 ; 列 INT 10h ; 显示时间字符串 LEA DX, time_string MOV AH, 09h INT 21h RET update_display ENDP END MAIN 我在按键识别上有问题(识别不出来),可能是 INT 16h的问题,能否帮我单独修改这里
06-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值