很好,搞搞期末,微机原理 我要开始啦bulabulabulabulabula.例题物理地址DS*16有效地址1.直接寻址2.直接寻址允许符号代替数值变量存的地址3.基址寻址16位用寄存器SI、DI、BX、BP存的有效地址下面是寄存器间接寻址116位232位除ESP和EBP默认段寄存器为SS外其余6个通用寄存器均默认段寄存器为DS下面是基址寻址4.基址加变址寻址变址寻址就是带了变址寄存器如SI、DI默认DS为段基址寄存器。基址加变址寻址就是带了基址寄存器变址寄存器5.基址变址相对寻址为什么是基址因为有效地址放在寄存器里了BP为什么是变址因为有变址寄存器SI为什么是相对段基址用SS因为基址寄存器用的BP已懵圈。1.段寄存器不能直接赋立即数2.内存之间不能直接传输数据3.LEA的目标必须是寄存器4.PUSH必须16/31可以扩展AL到AX5.MUL只有一个操作数首先咱们要知道一个指令大概长这样助记符 目标操作数源操作数然后我们检查操作数数量、操作数类型、操作数大小MUL是单操作数MOV是俩操作数类型是否允许组合寄存器、内存、立即数PUSH不能是8位1.MOV AX,SEG VAR0 MOV DS,AX2.MOV CL,4 SAL BX,CL是把BX左移四位逻辑左移SHL算数左移SAL移位次数置于CL中3.CMP DX, 0 ; 比较DX和0 JGE POSITIVE ; 如果DX ≥ 0跳到POSITIVE NEG DX ; 否则对DX取负 POSITIVE:CMP DX,0 JGE SKIP NEG DX SKIP:4.TEST AX, 3 ; 检查最后2位是否为0 JZ LAB0 ; 如果结果为0(能被4整除)跳转到LAB0AND AX, 3 CMP AX, 0 JE LAB0如果能被四整除后两位一定是00。3的二进制是11如果AX与11AND的结果是00那么AX一定能被4整除AND结果写到AX里进行比较JEJE和JZ一样结果为0跳转5.MOV DI, 2025 ; 设置目标地址(DI2025) MOV CX, 100 ; 设置计数器(CX100) MOV AL, 0 ; 要存储的值(AL0) CLD ; 清除方向标志(DF0地址递增) REP STOSB ; 重复执行: [ES:DI]←AL, DI←DI1DI当快递员CX记件数AL带零蛋CLD向前冲REP自动干MOV DI, 2025 ; 快递员站在2025号仓库起始地址 MOV CX, 100 ; 今天要送100个包裹计数器 MOV AL, 0 ; 每个包裹里是数字0要存储的值 CLD ; 设定方向向前走DF0地址递增 REP STOSB ; 开始自动送货 ; 动作分解 ; 1. 把AL的0放进[DI]仓库 ; 2. DI向前走1步1 ; 3. CX减1剩余包裹数 ; 重复直到CX0MOV SI, 2025 ; 起始地址 MOV CX, 100 ; 计数器 MOV AL, 0 ; 清零值 CLEAR_LOOP: MOV [SI], AL ; 清零当前字节 INC SI ; 地址1 LOOP CLEAR_LOOP ; CX减1若CX≠0则循环MOV SI, 2025 ; 把SI寄存器当作指针指向内存地址2025就像C语言的 int *p2025 MOV CX, 100 ; CX是计数器表示要清零100个字节像 for(int i100; i0; i--) MOV AL, 0 ; AL是8位寄存器存要写入的值0像 char zero0 CLEAR_LOOP: ; 循环开始标签像 while(true){ MOV [SI], AL ; 把0写入SI指向的内存位置像 *p zero INC SI ; 指针SI向后移动1字节像 p LOOP CLEAR_LOOP ; CX减1如果CX≠0就跳回循环开始像 if(--i0) goto loop; 假设在数据段已定义100字节的零缓冲区ZERO_BUFFER MOV SI, OFFSET ZERO_BUFFER ; 源地址全零 MOV DI, 2025 ; 目标地址 MOV CX, 100 ; 字节数 CLD REP MOVSB ; 复制零到目标区域ORG(origin)设置起始地址为150HDUP是复读机X4那行连续存了三个第一个是1234H第二个是当前地址(0160H)-20最后一个是(0162H)25$地址-10696H8555HDW低字节E9DW高字节07D的ascii44o的ascii6Fu75b62l6Ce653422H-69BBH3422H-69BBH1234H低字节34H1234H高字节12H-20低字节4CH-20高字节01H25低字节8BH?好像不太对25高字节01HDB放字节DW存字负数转补码字符串ASCIIDUP是复制$是当前位置小端记心间地址逐个加DATA SEGMENT ARRAY DB 23, 5, 17, 3, 8, 12 ; 定义无符号字节数组示例数据 LEN EQU $-ARRAY ; 计算数组长度 RESULT DW ? ; 存放结果的字变量 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START: MOV AX, DATA MOV DS, AX ; 设置DS指向数据段 ; 初始化假设前两个元素是最小的 MOV AL, ARRAY[0] ; AL 第一个数 MOV BL, ARRAY[1] ; BL 第二个数 ; 确保AL BL交换使AL存最小值BL存次小值 CMP AL, BL JBE NO_SWAP ; 如果AL BL不交换 XCHG AL, BL ; 否则交换AL和BL NO_SWAP: ; 遍历数组剩余元素从第3个开始 MOV CX, LEN - 2 ; 循环次数 数组长度 - 2 MOV SI, 2 ; 数组索引从2开始 FIND_MIN: MOV DL, ARRAY[SI] ; 取出当前元素 ; 比较当前元素与最小值AL CMP DL, AL JAE CHECK_SECOND ; 如果DL AL检查是否比BL小 ; 更新最小值和次小值 MOV BL, AL ; 原最小值变成次小值 MOV AL, DL ; DL成为新的最小值 JMP NEXT_ITER CHECK_SECOND: CMP DL, BL JAE NEXT_ITER ; 如果DL BL跳过 MOV BL, DL ; 否则更新次小值 NEXT_ITER: INC SI ; 移动到下一个元素 LOOP FIND_MIN ; 循环处理 ; 计算和并存入RESULT XOR AH, AH ; 清空AHAL是无符号字节 ADD AL, BL ; AL AL BL ADC AH, 0 ; 处理可能的进位和255时 MOV RESULT, AX ; 保存结果到RESULT MOV AH, 4CH INT 21H ; 程序结束 CODE ENDS END STARTDATA SEGMENT BUFFER DB 201 DUP(?) ; 输入缓冲区200字符1回车 X1 DB 0 ; 大写字母计数器 X2 DB 0 ; 小写字母计数器 X3 DB 0 ; 数字计数器 X4 DB 0 ; 其他字符计数器 MSG DB Input a string: $ DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START: MOV AX, DATA MOV DS, AX ; 设置DS指向数据段 ; 显示提示信息 MOV AH, 09H LEA DX, MSG INT 21H ; 从键盘读取字符串 MOV AH, 0AH LEA DX, BUFFER MOV BUFFER, 200 ; 设置最大长度 INT 21H ; 统计字符 LEA SI, BUFFER 2 ; SI指向实际输入的字符串首地址 MOV CL, BUFFER 1 ; CL实际输入字符数 MOV CH, 0 ; CX字符数 JCXZ DONE ; 如果输入为空则跳过 COUNT_LOOP: MOV AL, [SI] ; 取当前字符 ; 检查大写字母A-Z CMP AL, A JB NOT_UPPER CMP AL, Z JA NOT_UPPER INC X1 JMP NEXT_CHAR NOT_UPPER: ; 检查小写字母a-z CMP AL, a JB NOT_LOWER CMP AL, z JA NOT_LOWER INC X2 JMP NEXT_CHAR NOT_LOWER: ; 检查数字0-9 CMP AL, 0 JB OTHER CMP AL, 9 JA OTHER INC X3 JMP NEXT_CHAR OTHER: INC X4 ; 其他字符计数 NEXT_CHAR: INC SI ; 指向下一个字符 LOOP COUNT_LOOP ; CX减1循环直到CX0 DONE: MOV AH, 4CH INT 21H ; 程序结束 CODE ENDS END START一、数组求和中断程序; 数据段定义 DATA SEGMENT ARRAY DW -100, 200, -50, 300, 150 ; 定义带符号字数组 LEN EQU ($-ARRAY)/2 ; 计算数组长度 RESULT DD ? ; 保存结果的变量 DATA ENDS ; 代码段 CODE SEGMENT ASSUME CS:CODE, DS:DATA ; 主程序 MAIN PROC FAR MOV AX, DATA MOV DS, AX ; 设置中断向量(假设INT 63H中断向量已指向SUM服务程序) MOV BX, OFFSET ARRAY ; 数组起始地址 MOV CX, LEN ; 数组长度 INT 63H ; 调用中断服务程序 ; 保存结果 MOV WORD PTR RESULT, AX ; 低16位 MOV WORD PTR RESULT2, DX ; 高16位 MOV AH, 4CH INT 21H MAIN ENDP ; 中断服务程序SUM SUM PROC FAR PUSH SI PUSH DI PUSH CX XOR AX, AX ; 清空AX(低16位) XOR DX, DX ; 清空DX(高16位) MOV SI, BX ; 数组起始地址 SUM_LOOP: MOV DI, [SI] ; 取数组元素 ADD SI, 2 ; 指向下一个元素 ; 带符号数累加 CMP DI, 0 JGE POSITIVE ; 负数处理 NEG DI SUB AX, DI SBB DX, 0 JMP NEXT POSITIVE: ADD AX, DI ADC DX, 0 NEXT: LOOP SUM_LOOP POP CX POP DI POP SI IRET SUM ENDP CODE ENDS END MAIN二、8259A初始化程序; 主片8259A初始化 (端口320H,321H) MOV AL, 00010001b ; ICW1: 边沿触发,级联,需要ICW4 OUT 320H, AL MOV AL, 00011000b ; ICW2: 中断类型号18H-1FH OUT 321H, AL MOV AL, 00000100b ; ICW3: 从片连接在IR5 OUT 321H, AL MOV AL, 00011101b ; ICW4: 特殊完全嵌套,缓冲,非自动EOI OUT 321H, AL ; 第一个从片8259A初始化 (端口322H,323H) MOV AL, 00010001b ; ICW1: 边沿触发,级联,需要ICW4 OUT 322H, AL MOV AL, 10000000b ; ICW2: 中断类型号80H-87H OUT 323H, AL MOV AL, 00000101b ; ICW3: 从片ID5(连接主片IR5) OUT 323H, AL MOV AL, 00001001b ; ICW4: 非特殊完全嵌套,缓冲,非自动EOI OUT 323H, AL ; 第二个从片8259A初始化 (端口324H,325H) MOV AL, 00010001b ; ICW1: 边沿触发,级联,需要ICW4 OUT 324H, AL MOV AL, 10001000b ; ICW2: 中断类型号88H-8FH OUT 325H, AL MOV AL, 00000101b ; ICW3: 从片ID5(连接主片IR5) OUT 325H, AL MOV AL, 00001001b ; ICW4: 非特殊完全嵌套,缓冲,非自动EOI OUT 325H, AL三、四、8254计数器初始化; 计数器0初始化(方式2,二进制计数,初值216) MOV AL, 00110100b ; 控制字: 00计数器,先低后高字节,方式2,二进制 OUT 7F3H, AL MOV AL, 216 ; 计数初值低字节 OUT 7F0H, AL MOV AL, 0 ; 计数初值高字节 OUT 7F0H, AL ; 计数器1初始化(方式0,BCD计数,初值7500) MOV AL, 01110001b ; 控制字: 01计数器,先低后高字节,方式0,BCD OUT 7F3H, AL MOV AL, 00H ; 计数初值低字节(7500的BCD码: 7500H) OUT 7F1H, AL MOV AL, 75H ; 计数初值高字节 OUT 7F1H, AL ; 计数器2初始化(方式3,二进制计数,初值35FFH) MOV AL, 10110110b ; 控制字: 10计数器,先低后高字节,方式3,二进制 OUT 7F3H, AL MOV AL, 0FFH ; 计数初值低字节 OUT 7F2H, AL MOV AL, 35H ; 计数初值高字节 OUT 7F2H, AL ; 读取计数器2当前值 MOV AL, 10000000b ; 控制字: 锁存计数器2当前值 OUT 7F3H, AL IN AL, 7F2H ; 读低字节 MOV AH, AL IN AL, 7F2H ; 读高字节 XCHG AH, AL ; 调整字节顺序 MOV COUNT, AX ; 保存到COUNT变量五、8237A初始化程序; 8237A初始化 ; 先发送主清除命令 MOV AL, 0 OUT 0A00DH, AL ; 主清除命令 ; 设置命令寄存器 MOV AL, 00000000b ; 正常时序,固定优先级,正常写,DREQ高有效,DACK高有效 OUT 0A008H, AL ; 设置模式寄存器(通道1,单字节传输,读传输,自动预置禁止) MOV AL, 01001001b ; 通道1,模式49H OUT 0A00BH, AL ; 设置地址寄存器(低16位) MOV AX, OFFSET BUFF OUT 0A002H, AL ; 低字节 MOV AL, AH OUT 0A002H, AL ; 高字节 ; 设置地址寄存器(高4位,页面寄存器) MOV AL, SEG BUFF ; 取段地址 AND AL, 0FH ; 取高4位 OUT 0A083H, AL ; 通道1页面寄存器(A000H83H) ; 设置字节计数器 MOV AX, 1500 ; 传输字节数 DEC AX ; 8237A计数为n-1 OUT 0A003H, AL ; 低字节 MOV AL, AH OUT 0A003H, AL ; 高字节 ; 清除屏蔽位,启动DMA MOV AL, 00000001b ; 屏蔽寄存器: 仅通道1非屏蔽 OUT 0A00FH, AL复习首先就是补码、ASCII码有一个计算题用到。比如负数要补码也就是二进制取反加1比如字母直接ASCII。CPU引脚这里应该是CPU引脚功能地址线、数据线物理地址、逻辑地址、有效地址。物理地址就是CPU最终访问内存单元的实际地址20位00000H~FFFFFH计算公式物理地址段地址segment*16偏移地址offset逻辑地址就是程序员在汇编语言中使用的地址形式由段地址偏移地址组成如DS:SI物理地址的计算公式好像也是这样有效地址EA是偏移地址的计算结果用于确定操作数在段内的位置由基址寄存器BX/BP变址寄存器SI/DI位移量dispplacement计算方式EA[BX/BP][SI/DI]8/16位位移量还是有了DS段地址然后公式计算物理地址段寄存器CS, DS, ES, SS与偏移量寄存器IP, SI, DI, SP, BP的对应关系段寄存器主要用途默认偏移量寄存器典型应用场景CS代码段Code SegmentIP指令指针取指令CSIP指向下一条指令DS数据段Data SegmentBX/SI/DI访问数据如MOV AX,[BX]ES附加段Extra SegmentDI串操作目标串操作如MOVSB使用DS:SI-ES:DISS堆栈段Stack SegmentSP/BP堆栈操作如PUSH AX使用SS:SP寻址方式会看弄明白源操作数和目标操作数的寻址方式指令集判断指令的对错mov d,s两个操作数什么情况下可以赋值两个操作数位数相等、目标操作数必须能重写x86不能直接从内存到内存需通过寄存器中转各种指令的错误使用1.操作数类型不匹mov ax,blbl是8位ax是16位2.立即数不能直接赋值给段寄存器要通过中间寄存器中转3.不能内存到内存4.特权指令不能乱用5.错误的栈操作太多了这也。。。debug里的调试指令各类伪指令dos中断中断向量表断点现场中断的整个过程外部中断可屏蔽不可屏蔽内部中断异常陷阱8259A8255A? 8254/8253? 8237A?额外补一张