求大神求助 汇编! 题目要求 求出php 数组常见题目中各项的和 那个ADD INC LOAD的作用各是什么 谢谢

当前位置: >>
汇编语言习题集
习题说明:英语习题全部上网,可在网上完成。网址: http://www10./ie_mulingling/index.asp?csub=汇编语言双语教学 作业辅导 作业网址:http://www10./ie_mulingling/zuoye_list.asp 根据教学内容我们还自己编写了习题.选择习题11.Find the decimal integer that is representd by each of these 2?s complement numbers: (1)FFH (2)0H (3)F3E1H (4)B64AH (5)2EH (6)10H (7)1FH (8)ABH 2.Find the BCD representation of each of the following decimal numbers: (1)12 (2)24 (3)68 (4)127 (5)128 (6)255 (7)1234 (8)2458 3.Find the heximal representation of each of the following binary number. (1)b (2)b (3)10b (4)11110b (5)111110b (6)b (7)b (8).Find the decimal number that is represented by each of these BCD number. (1) (2) (3) (4) (5) (6) (7) (8).Find the byte-length 2?s complement representation of each of the following decimal numbers: (1)0 (2)?127 (3)127 (4)?57 (5)126 (6)?126 (7)?128 (8)11947 6.Find the word-length 2?s complement representation of each of the following decimal numbers: (1)?1 (2)?10 (3)845 (5)?923 (6)100 (7)15000 7.Find the doubleword-length 2?s complement representation of each of the following decimal numbers: (1)?1 (2)?10 (3)23 (5)?100 8.Find the signed decimal integer that is representd by each of these 2?s complement numbers: (1) B64AH (2)F3E1H (3)6F20H (4)00E1H 9.Find the signed decimal integer that is representd by each of these 2?s complement numbers: (1) 1000B64AH (2)98C2417DH (3)FFFFFE03H (4)H 10.Complete the following caculations: (1) (2) (3) (4)01 (5)1011 ? 1001 (6)1011 ? 1001 (7)~1011 (8)1011 ? 1001 11.Find the range of decimal integers that can be stored in 2?s complement form in a byte. 12.Find the range of decimal integers that can be stored in 2?s complement form in a doubleword. 13.数码 0~9、大写字母 A~Z、小写字母 a~z 对应的 ASCII 码分别是多少?ASCII 码为 0dH、0aH 对应的是什么字符? 14.计算机中有一个“”编码,如果把它认为是无符号数,它是十进制的什么 数?如果认为它是 BCD 码,则表示什么数?又如果它是某个 ASCII 码,则代表哪个字符? 15.What is overflow? What is carry? What?s the difference between them ? 16.Determine whether overflow or carry occurs 。 (1)003FH+02A4H (2)1B48H+39E1H (3)6C34H+5028H (4)7FFEH+0002H (5)FF07H+06BDH (6)2A44H+D9CCH (7)FFE3H+FC70H (8)FE00H+FD2DH (9)FFF1H+8005H (10)8ADCH+EC78H (11)9E58H?EBBCH (12)EBBCH?9458H (13)EBBCH?791CH (14)791CH CEBBCH习题21.罗列 IA-32CPU 的 8 位,16 位和 32 位通用寄存器,并说明各自的作用。 2.什么是标志,它有什么用途?状态标志和控制标志有什么区别?画出标志寄存器 EFLAGS,说明各个标志的位置和含义。 3.字和双字在存储器中如何存放,什么是“小端方式”?对字和双字存储单元,什么 是它们的对齐地址?为什么要对齐地址? 4.Suppose that you have an Intel 8086 . Find the five-hex-digit address that corresponds to each of these segment:offset pairs: (1)FFFH:0 (2)40H:17H (3)H (4)B821H:4567H 5.实地址模式和保护模式模式下段寄存器的内容有什么区别? 6.什么是段选择器?什么是段描述符?什么是描述符表?它们之间有什么关系? 7.存储器模型和处理器的操作模式有什么关系? 8.数据的默认段是哪个,是否允许其他段存放数据?如果允许,如何实现,有什么要 求? 9.How many bytes of memory are there in PC based IA-32CPU? 10.什么是端口?如何编址端口?习题31.伪指令语句与硬指令语句的本质区别是什么?伪指令有什么主要作用? 2.什么是标识符,汇编程序中标识符怎样组成? 3.什么是保留字,汇编语言的保留字有哪些类型,并举例说明。 4.Name and describe the three types of assembly language statements. 5.汇编语言程序的开发有哪 4 个步骤?分别利用什么程序完成、产生什么输出文件? 6.区分下列概念:(1)变量和标号;(2)数值表达式和地址表达式;(3)符号常 量和字符串常量。 7.画图说明下列语句分配的存储空间及初始化的数据值:(1) byte_var byte ?ABC?,10,10h,?EF?,3 dup(-1,?,3 dup(4)) (2) word_var word 10h,-5,?EF?,3 dup(?)8.请设置一个数据段 mydataseg,按照如下要求定义变量: (1) my1b 为字符串变量:Personal Computer (2) my2b 为用十进制数表示的字节变量:20 (3) my3b 为用十六进制数表示的字节变量:20 (4) my4b 为用二进制数表示的字节变量:20 (5) my5w 为 20 个未赋值的字变量 (6) my6c 为 100 的常量 (7) my7c 表示字符串:Personal Computer 9.变量和标号有什么属性? 10. MASM 定义了哪 7 种存储模式?TINY 和 SMALL 模式创建什么类型 (EXE 或 COM) 程序?设计 32 位应用程序应该采用什么模式? 11.分别写出实模式和保护模式下的程序格式框架。 12.设在某个程序中有如下段定义,请画图说明内存空间的分配以及内容。.data ORG 100h VARW WORD h VARB BYTE 3,4 AGLIN 4 VARD DWORD h EVEN BUFF BYTE 10 DUP(?) MESS BYTE ?HELLO? MESS_VARB_OFFSET DWORD OFFSET VARB+OFFSET MESS VAR_TYEP BYTE TYPE BUFF+TYPE MESS+TYPE VARD VAR_SIZE BYTE SIZE VARW+SIZE BUFF+SIZE MESS VAR_LENGTH BYTE LENTH VARW+LENTH VARD BUFF_LS BYTE LENTH BUFF+SIZE VARW BEGIN_TYPE BYTE TYPE BEGIN BEGIN_OFFSET DWORD OFFSET BEGIN .code BEGIN: RET END BEGIN习题41. real mode, suppose that DS=2000H、 = 0100H、 = 0002H, In BX SI memory [20100H]~ [20103H] store data 12, 34 ,56 ,78H,[21200H]~[21203H] store data 2A, 4C, B7 ,65H. Give the values after each instruction performed.(1) mov ax,1200h (2) mov ax,bx (3) mov ax,[1200h] (4) mov ax,[bx] (5) mov ax,[bx+1100h] (6) mov ax,[bx+si] (7) mov ax,[bx][si+1100h]2.控制转移类指令中有哪三种寻址方式? 3.What is short jump, near jump and far jump?What are intersegment jump and intrasegment jump ? 4.实模式下,假设 DS=2000H,BX=1256H,SI=528FH,位移量 TABLE=20A1H, [232F7H]=3280H,[264E5H]=2450H,试问执行下列段内间接寻址的转移指令后,转移的有 效地址是什么?(1) jmp bx (2) jmp table[bx] (3) jmp [bx][si]5.什么是操作码、操作数和寻址方式?有哪三种给出操作数的方法? 6.什么是有效地址 EA?80x86 的操作数如果在主存中,有哪些寻址方式可以存取它? 7.Describes the addressing mode in each instruction. Suppose that BX=2000H,DI=40H, give the values of DX or EA.(1) mov dx,[1234h] (2) mov dx,1234h (3) mov dx,bx (4) mov dx,[bx] (5) mov dx,[bx+1234h] (6) mov dx,[bx+di] (7) mov dx,[bx+di+1234h] (8)mov eax, [ebx+4*edx+20] (9)mov eax,[ebx][edx]习题51.已知用于 LED 数码管的显示代码表为:LEDtable byte 0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8h byte 80h,90h,88h,83h,0c6h,0c1h,86h,8eh它依次表示 0~9、A~F 这 16 个数码的显示代码。现编写一个程序实现将字节变量 lednum 中的一个数字(0~9、A~F)转换成对应的 LED 显示代码。 2.Write a piece of code sequence: store three grades in array, caculate the average grade of them. 3.设 X、Y、Z、V 均为 16 位带符号数,分别装在 X、Y、Z、V 存储单元中,阅读如 下程序段,得出它的运算公式,并说明运算结果存于何处。mov ax,X imul Y mov cx,ax mox bx,dx mov ax,Z cwd add cx,ax adc bx,dx sub cx,540 sbb bx,0 mov ax,V cwd sub ax,cx sbb dx,bx idiv X4.请分别用一条汇编语言指令完成如下功能: (1)把 EBX 寄存器和 EDX 寄存器的内容相加,结果存入 EDX 寄存器。 (2) 用寄存器 EBX 和 ESI 的基址变址寻址方式把存储器的一个字节与 AL 寄存器的内 容相加,并把结果送到 AL 中。 (3)用 EBX 和位移量 0B2H 的寄存器相对寻址方式把存储器中的一个字和 ECX 寄存 器的内容相加,并把结果送回存储器中。 (4) 用的间接寻址方式把存储器单元 H 中的一个字与数 3412H 相加, 并把结 果送回该存储单元中。 (5)把数 0A0H 与 AL 寄存器的内容相加,并把结果送回 AL 中。 5.给出下列各条指令执行后的 AL 值,以及 CF、ZF、SF、OF 和 PF 的状态:mov al,89h add al,al add al,9dh sub al,al dec al inc al6.Find the error occurs in the following instructions:(1)mov cx,dl (3)mov es,1234h (5)mov al,300 (7)mov eax,ebx+edi (9)movzx ax, 82h (11)mov al, 1200 (2)mov eip,ax (4)mov es,ds (6)mov [esp],ax (8)mov 20h,ah (10)mov [eax],10 (12)mov 100,eax (14)shld eax, var, 8(13)mov [esi], [edi]7.分别写出实现 128 位二进制数的加法和减法的序列指令。 8.写出实现下面功能的指令序列: (1)x 是 16 位有符号数,y 是 16 位二进制有符号数, z=x+y (2)x 是 16 位有符号数,y 是 32 位二进制有符号数, z=x+y (3)x 是 32 位有符号数,y 是 8 位二进制有符号数, z=x+y (4)x 是 32 位有符号数,y 是 32 位二进制有符号数, z=x×y (5)x 是 16 位无符号数,y 是 16 位二进制无符号数, z=x÷y (6)x 是 16 位有符号数,y 是 16 位二进制有符号数, z=x÷y (7)x 是 32 位有符号数,y 是 16 位二进制有符号数, z=x×y (8)x 是 16 位有符号数,y 是 16 位二进制有符号数, z=x×y 9.编写程序实现算术表达式:m=(x*5)/(y mod z),其中的 x、y、z、m 都是 32 位有符号 数。 10.设(eax)=0c5ffh,(ebx)=9e00h,试分析下列各条指令执行后 ax、bx 或 cx 寄存 器以及 ZF、SF、CF、OF、PF 的状态。 (1)and eax, ebx (2)xor eax,0ff00h (3)or eax, 0ff00h (4)shl eax, 4 (5)sar ebx, 4 (6)ror ebx, 16 (7)bt ebx, 8 (8)bsf ecx, ebx 11.编写下列各功能程序段: (1)al 寄存器的各位变反; (2)ebx 寄存器的低 4 位置 1; (3)eax 寄存器的低 4 位清零; (4)ecx 寄存器的低 4 位变反; (5)采用移位指令实现 ax?5,结果送 bx,要求 ax 的内容保持不变; (设结果无溢出) 12.编写程序分解 EAX 寄存器的内容:取高 7 位存入双字变量 value1,取中间 15 位存 入双字变量 value2,取最后 10 位存入双字变量 value3。 13.编写完整的程序完成例 5-47 的功能:利用作者提供的宏指令 ReadUDecByte 从键 盘接收一个字节的十进制数,利用例题 5-47 的代码,将这个十进制数转换成十六进制字符 存放到 HexStr 中,用输出字符串宏(WriteString)显示转换的结果。习题61.转移指令有几种类型?各自有什么特点? 答:段内近转移,段内短转移,段间远转移 直接寻址, 间接寻址 2.指出下面转移指令的类型(相对近转移,相对短转移,间接转移) 。.DATA addrSore DWORD ? .CODE ?? again: ?? (3 instructions) jmp again; 短转移 ?? (200 instructions) ?? jmp again ;近转移 ?? jmp addrStore; 段内间接转移 ?? jmp eax ?? jmp [edi]3.代码段有以下指令:ADD EAX, EBX JNO L1 JNC L2 SUB EAX, EBX JNC L3 JNC L4 JMP SHORT L5如果 EAX 和 EBX 的内容如下: (1)EAX=0102147BH,EBX=120180DCH ;L1 (2)EAX=H,EBX=800080DCH; L1 (3)EAX=D0230000H,EBX=9FD0000H; L3 (4)EAX=94B70000H,EBX=B568000H; L1 指令执行完后,程序怎样转移? 4.假设 EAX 和 EBX 的内容是无符号数,ECX 和 EDX 的内容是有符号数,请用比较 指令实现以下判断: (1)如果 EDX 的内容大于 ECX 的内容,则转去执行 L1; cmp edx, ecx jg L1 (2)如果 EAX 的内容大于 EBX 的内容,则转去执行 L2; cmp eax, ebx ja L2 (3)如果 ECX=0,则转去执行 L3; cmp ecx, 0 jz L3 (4)EAX-EBX 是否会发生溢出,如果发生溢出则转去执行 L4; sub eax, ebx jo L4 (5)如果 EBX 的内容小于 EAX 的内容,则转去执行 L5; cmp ebx, eax jb L5 (6)如果 ECX 的内容小于 EDX 的内容,则转去执行 L6。 cmp ecx, edx jl L6 5.已知 EAX=0000004FH,VALUE=FFFFFFFFFFFFFF38H。请指出下面每一个语句是 否会引起转移?(a) cmp eax, N (b) cmp eax, value
Y (c) cmp eax,04 Y (d) cmp eax, 79 N (e) cmp value,0 N (f) cmp value,-200Y (g) cmp eax, 200 y (h) add value,200 N6.编写程序测试 STATUS 中的状态:如果 STATUS=0,则转去执行 L0;如果 D0,D3, D5 位为 1 则转去执行 L1;如果 D31,D29 为 0 则转去执行 L2;如果 D15,D14,D13 为 1,则 转去执行 L3。 test status, FFFFH jz L0 test status , 29H jne L1 test status, C0000000H jz L2 test status, 00e00000H jne L3 7.指出下面每一个循环的循环次数:(a) mov ecx,10 again: ?? loop again 10 (b) mov ecx,1 again: ?? loop again 1 (c) mov ecx,0 again: ?? loop again
(c) mov ecx,-1 again: ?? loop again 8.编写一个程序将双字数组 ARRAY 中的每一个元素加 1(不考虑溢出) 。 .386 .model flat, stdcall .data array dword 35,89,-39,89,45,78,-90 count equ $-array .code startup: mov ecx, count mov ebx, offset array again: inc [ebx] inc ebx loop again ret end start 9.在双字型无序数组中找出最大数,存入 max 单元中。 .386 .model flat, stdcall .data array dword 35,89,-39,89,45,78,-90 count equ $-array .code start: mov ecx, count mov ebx, offset array mov eax, [ebx] inc ebx again: cmp eax, [ebx] jb next mov eax, [ebx] next: inc ebx loop again ret end start 10.在 x、y、z 三个双字型变量中存放着 3 个无符号数,若 3 个数均不为 0,求出它们 的和存入 w 单元中(不考虑溢出) ;若有一个以上的数为 0,将其他两个单元也清 0。 .386 .model flat, stdcall .data x dword ? y dword ? z dword ? .code start: cmp x, 0 jz cls cmp y, 0 jz cls cmp z, 0 jz cls mov eax, x add eax, y add eax, z mov w, eax jmp endpro cls: and x, 0 and y, 0 and z, 0 endpro: ret end start 11.把一个含有 100 字节型数据的数组分成两组:正数数组 P 和负数数组 N。 .386 .model flat, stdcall .data array byte 100 dup(?) P byte 100 dup(?) N byte 100 dup(?) .code start: mov ecx, 100 mov ebx, offset array mov esi, offset P mov edi, offset N again: mov eax, [ebx] cmp eax,0 jl negative mov [esi], eax jmp next negative: mov [edi], eax next: inc ebx inc esi inc edi loop again endpro: ret end start 12.试用转移表法实现对字型数组的操作。如果输入“1” ,对数组元素求和并显示;如 果输入“2” ,求数组平均值并显示;如果输入“3” ,找出数组中所有的负数并显示;如果输 入“4” ,找出数组中所有的非 0 项,并显示。 (不考虑溢出) .386 .model flat, stdcall include io32.inc .data array word 23,677,-90,23,-49 count equ $-array jmptable dword one, two, three, four .code start: xor eax, eax ReadChar al and eax, 0fh dec eax jmp jmptable[eax*4] one: mov ebx, offset array xor eax, eax again: add eax, [ebx] inc ebx loop again WriteDedDword eax jmp endpro two: mov ebx, offset array xor eax, eax xor ecx again: add eax, [ebx] inc ebx inc ecx loop again cdq idiv ecx WriteDedDword eax jmp endpro three: mov ebx, offset array again: cmp [ebx], 0 jge next mov eax, [ebx] WriteDecDword eax next: inc ebx loop again jmp endpro four: mov ebx, offset array again: cmp [ebx], 0 je next mov eax, [ebx] WriteDecDword eax next: inc ebx loop again endpro: ret end start 13.假设在 BUF 字节型数组中有 64B 个有符号数,试统计其中正数的个数,采用宏指 令 WriteUDecDword 显示统计结果。 .386 .model flat, stdcall include io32.inc .data buf byte 64 dup(?) .code start: mov ecx, 64 xor eax, eax mov ebx, offset buf again: cmp [ebx], 0 js next inc eax next inc ebx loop again ret end start 14.编写程序计算 1+2+3+4+?+99+100,并将结果显示在屏幕上。 .386 .model flat, stdcall include io32.inc .code start: xor eax, eax mov ebx, 1 again: add eax, ebx inc ebx loop again ret end start 15.把以“$”结束的一字符串中的大写字母改为小写字母。 .386 .model flat, stdcall .data string byte “dfjhAgshdgG”, ?$? .code start: mov ebx, offset string mov ecx, length string-1 again: cmp [ebx], 41h jb next cmp [ebx], 5ah ja next and [ebx], 20h next: inc ebx loop again ret end start 16.设有一数组中存放着 80 个学生的成绩(0~100) ,试统计 0~59 分,60~69 分, 70~79 分,80~89 分,90~100 的学生的个数,分别存放在 scoreE,scoreD,scoreC,scoreB 及 scoreA 单元中并显示。 .386 .model flat, stdcall .data array byte 80 dup(?) scoreE byte 0 scoreD byte 0 scoreC byte 0 scoreB byte 0 scoreA byte 0 .code start: mov ebx, offset array xor ecx, ecx again: ReadSDecByte al cmp al, -1 je contine mov [ebx], al inc ecx jmp again mov ebx, offset array agagin1: cmp [ebx], 59 jbe L1 cmp [ebx], 69 jbe L2 cmp [ebx], 79 jbe L3 cmp [ebx], 89 jbe L4 L1: inc scoreE jmp ebdpro L2: inc scoreD jmp ebdpro L3: inc scoreC jmp ebdpro L2: inc scoreB jmp ebdpro inc scoreA ret end start 17.在输入输出子程序库中,经常需要进行码制的转换和输入字符合法性的判断,编写 程序完成下面的功能。 (1)编写程序判断 AL 中的内容是否为字符“-”和“0”~“9” 。 cmp al, ‘-‘ jz ok cmp al, ‘0’ jb not cmp al, ‘9’ ja not ok: ? jmp exit not:? exit: (2)编写程序判断 AL 中的内容是否为字符“0~9”和“A”~“F”, “a”~“f”。 cmp al, ‘0’ jb not cmp al, ‘9’ ja not cmp al, ‘A’ jb not cmp al, ‘F’ ja not cmp al, ‘a’ jb not cmp al, ‘f’ ja not ok: ? jmp exit not:? exit: (3)编写程序判断 AL 中的内容是否为字符“0”和字符“1”。 cmp al, ‘0’ je Yes cmp al, ‘1’ ja Yes (4)编写程序将 EAX 的内容转换为二进制字符串。 .data string byte 32 dup(?),0 .code start: mov ebx, offset string mov ecx, 32 again: rol eax, 1 jc one mov [ebx], 30h one: mov [ebx], 32h inc ebx loop again (5)编写程序将 EAX 的内容转换为十六进制字符串。 .data ASCII byte 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h byte 41h,42h,43h,44h,45h,46h.codemov edi,offset HexStr mov ebx,offset ASCII mov ecx, 8 eaxsave1: rol eax,4 push eax and al,0fh xlat CS:ASCII mov [edi],al pop eax inc edi loop eaxsave1 ret ;保存 ;转换 al 的低 4 位 ;修改指针 ;从高位开始转换 ;暂存数据 ;取得一位十六进制数 ;edi=HexStr 的首地址 ;EBX 指向 ASCII 码表(6)编写程序将 EAX 的内容转换为无符号十进制字符串。.datastring byte 11 dup(?) .code mov edi, offset stringxor edx, edx xor ecx, ecx mov ebx, 10 a10:div ebx push edx inc ecx xor edx, edx cmp eax, edx jnz a10 a20: pop eax add al,?0? mov [edi],al inc edi loop a20 mov byte ptr [edi],0 ;商是否为 0 ;商不是 0,跳转到 a10 ;商为 0,从堆栈中取出余数 ;转换为字符 ;存入[edi] ;修改地址指针 ;取下一个余数 ;字符串以 0 结尾 ;除数 10 ;edx.eax÷余数进栈 ;记录余数个数(7)编写程序将 EAX 的内容转换为有符号十进制字符串,负数字符串以“-”引导。.datastring byte 11 dup(?) .code mov edi, offset stringtest eax, 判断 eax 是否为负数 jns convert neg eax inc edi convert: xor edx, edx xor ecx, ecx mov ebx, 10 a10:div ebx push edx inc ecx xor edx, edx cmp eax, edx jnz a10 a20: pop eax add al,?0? mov [edi],al inc edi loop a20 mov byte ptr [edi],0;是 0 和正数跳转到如果是负数,求绝对值 ;指向下一个字节 ;转换为字符串mov byte ptr [edi], ?-? ;字符串的一个字符为‘-’;除数 10 ;edx.eax÷余数进栈 ;记录余数个数 ;商是否为 0 ;商不是 0,跳转到 a10 ;商为 0,从堆栈中取出余数 ;转换为字符 ;存入[edi] ;修改地址指针 ;取下一个余数 ;字符串以 0 结尾(8)按照(4)~(70)的要求转换 AX 寄存器的内容。 (9)按照(4)~(7)的要求转换 AL 寄存器的内容。 (10)编写程序将二进制字符串表示的数据存入 EAX 寄存器。.data string byte “” .code mov ecx, 32 mov ebx, offset string xor eax, eax again: xor edx, edx mov dl, [ebx] shl edx,31 shld eax,edx, 1 inc ebx loop again(11)编写程序将十六进制字符串表示的数据存入 EAX 寄存器。.data string byte “12ab4c35”,0 .code mov ebx, offset String xor ecx,ecx mov cl, 8 xor eax, eax again: mov dl,[ebx] cmp dl, '9' jbe L1 sub dl,'A' add dl,10 jmp L2 L1:and dl,0fh L2:shl edx,28 shld eax,edx,4 inc ebx loop again(15)编写程序将十进制字符串表示的无符号数据存入 EAX 寄存器。.data string byte “345”,0 .code mov edi, offset string mov al,[edi] cmp al,0 jz done and al, 0fh mov ebx, eax inc edi read1: xor eax,取出一个字符 ;如果是 0,字符串跳转到如果不是 0,将字符转换为数据 0~9 ;如果是 0,字符串跳转到 如果不是 0,将字符转换为数据 0~9 ;取出一个字符mov al,[edi] cmp al,0 jz done and al, 0fhshl ebx,1;ebx*2 ;利用移位指令,实现原来的数值乘 10:EBX←EBX×10 mov edx,edx=ebx*2 shl ebx,1;ebx*4 shl ebx,1;ebx*8 add ebx,ebx=ebx*10 add ebx,eax inc edi jmp read1 ;继续转换下一个字符 ;加上原来的数值乘以 10one:mov eax,设置出口参数(16)编写程序将十进制字符串表示的有符号数据存入 EAX 寄存器。.data string byte “-345”,0 flag dword ? .code mov al , [edi] cmp al, ?-? jnz convert mov flag,1 inc edi convert: mov al,[edi] cmp al,0 jz done and al, 0fh mov ebx, eax inc edi read1: xor eax,取出一个字符 ;如果是 0,字符串跳转到如果不是 0,将字符转换为数据 0~9 ;如果是 0,字符串跳转到 如果不是 0,将字符转换为数据 0~9 ;取出一个字符 ;判断字符串中第一个字符是否为‘?’ ;不是‘?’,直接转换 ;flag=1,符号位为 1 ;指向数字字符 ;转换为对应的 32 位无符号数mov al,[edi] cmp al,0 jz done and al, 0fhshl ebx,1;ebx*2 ;利用移位指令,实现原来的数值乘 10:EBX←EBX×10 mov edx,edx=ebx*2 shl ebx,1;ebx*4 shl ebx,1;ebx*8 add ebx,ebx=ebx*10 add ebx,eax inc edi jmp read1 cmp flag,1符号位为 0,表示是正数,跳转到符号位为 1,表示是负数,求补 ;继续转换下一个字符 ;加上原来的数值乘以 10one:mov eax,设置出口参数done: (17)按照(10)~(13)的要求转换字符串存入 AX 寄存器。 (18)按照(10)~(13)的要求转换字符串存入 AL 寄存器。习题71.子程序定义的一般格式是怎样的?子程序入口为什么常有 PUSH 指令、出口为什 么有 POP 指令?下面的程序段有什么不妥吗?若有,请改正。crazy PROC删去 xor ax,ax xor dx,dx again: add ax,[bx] adc dx,0 inc bx inc bx loop again;增加 pop axret endp crazy ;crazy endp答:保存寄存器 ;指令 ;恢复寄存器 ret name endp push 指令和 pop 指令通常用于保护和恢复寄存器 2.子程序的参数传递有哪些方法,请简单比较。 答:寄存器,共享变量,堆栈 3.下面的指令执行后的结果是什么? (1)ESP=H,ECX=01A25B74H, PUSH ECX PUSHW 10 ESP=? ECX=? 答:esp==6000FFAH, ecx 不变 (2)ESP=02000B7CH, EBX=H PUSHD 20 PUSH EBX ESP=? EBX=? 答:esp=02000b7ch-12=2000B70H, ebx 不变 (3)ESP=0000F83AH,EAX=H PUSH EAX PUSHW 30 POP BX POP ECX ECX=? ESP=? EAX=? BX=? 答:esp=000083Ah-6=0000834H, bx=30, ecx=H, eax 不变 4.假设主程序中有子程序调用语句:CALL Myproc。如果这条 call 指令所在地址是 h, esp=h,这条 call 指令执行后, 堆栈中保存的返回地址是多少?ESP=? 答:返回地址:h esp=00405fbch 5. 子程序返回值为 EAX, 在程序的入口和返回处是否可以用 PUSHAD 和 POPAD 来保 存和恢复寄存器? 答:不可以 6.采用堆栈传递参数的一般方法是什么,为什么应该特别注意堆栈平衡问题。 答:通过堆栈传递参数,主程序将数组的偏移地址和元素个数压入堆栈,然后调用子程 序;子程序通过 EBP 寄存器从堆栈相应位置取出参数(非栈顶数据) ,用堆栈传递参数时, 要时刻注意堆栈的分配情况,保证参数的正确存取以及子程序的正确返回。 清除堆栈中的入口参数 7. 试写出子程序的入口代码: 为一个字类型和一个双字类型的局部变量预留堆栈空间, 并指出如何在子程序中访问局部变量? 答:mov ebp, esp sub esp , 6 字变量:[ebp+2] 双字变量:[ebp+6] 8.什么是子程序的嵌套、递归和重入? 答:子程序内包含有子程序的调用就是子程序嵌套。 当子程序直接或间接地嵌套调用自身时称为递归调用, 含有递归调用的子程序称为递归 子程序。 子程序的重入是指子程序被中断后又被中断服务程序所调用, 能够重入的子程序称为可 重入子程序。 9.请按如下子程序说明编写子程序。;子程序功能:把用 ASCII 码表示的两位十进制数转换为对应二进制数 ;入口参数:DH=十位数的 ASCII 码,DL=个位数的 ASCII 码 ;出口参数:AL=对应的二进制数答:decTobin proc shl dh, 4 or dh, dl mov al, dl ret decTobin endp 10.写一个子程序,根据入口参数 AL=0/1/2,分别实现对大写字母转换成小写、小写 转换成大写或大小写字母互换。欲转换的字符串在 string 中,用 0 表示结束。 答:convert proc mov ebx, 1 cmp al, 0大写变小写 A1: mov bl, string[ebx] inc ebx cmp bl, 41h jb A1 cmp bl, 5ah ja A1 xor bl, 20h mov string[ebx],bl cmp bl, 20h jz endpro jmp A1 next: cmp al, 1 jne next1 ;小写变大写 A2: mov bl, string[ebx] inc ebx cmp bl, 61h jb A2 cmp bl, 7ah ja A2 xor bl, 20h mov string[ebx],bl cmp bl, 20h jz endpro jmp A2 next1: cmp al, 2大小写互换 A3: mov bl, string[ebx] inc ebx cmp bl, 41h jb A3 cmp bl, 5ah jbe c1 cmp bl, 61h jb A3 cmp bl, 7ah ja A3 C1: xor bl, 20h mov string[ebx],bl cmp bl, 20h jz endpro jmp A2 endpro: ret convert endp 11.编制一个子程序把一个 32 位二进制数用十六进制形式在屏幕上显示出来,分别运 用如下 3 种参数传递方法,并用一个主程序验证它。 (1)采用 EAX 寄存器传递这个 32 位二进制数。 答:binToHex proc mov ebx, eax mov ecx, 8 again: rol ebx, 4 mov eax, ebx and ebx, 0000000fh or bl, 30h cmp ebx, 0ah jb disp1 add ebx, 7 disp1: WriteChar bl dec ecx cmp ecx, 0 jne agaian ret binTohex endp (2)采用 dwordTEMP 变量传递这个 32 位二进制数。 答:binToHex proc mov eax, dwordTEMP mov ebx, eax mov ecx, 8 again: rol ebx, 4 mov eax, ebx and ebx, 0000000fh or bl, 30h cmp ebx, 0ah jb disp1 add ebx, 7 disp1: WriteChar bl dec ecx cmp ecx, 0 jne agaian ret binTohex endp (3)采用堆栈方法传递这个 32 位二进制数。 binToHex proc x:dword mov eax, x mov ebx, eax mov ecx, 8 again: rol ebx, 4 mov eax, ebx and ebx, 0000000fh or bl, 30h cmp ebx, 0ah jb disp1 add ebx, 7 disp1: WriteChar bl dec ecx cmp ecx, 0 jne agaian ret binTohex endp 12.设有一个数组存放学生的成绩(0~100) ,编制一个子程序统计 0~59 分、60~69 分、 70~79 分、 80~89 分、 90~100 分的人数, 并分别存放到 scoreE、 scoreD、 score C、 score B 及 score A 单元中。编写一个主程序与之配合使用。 答: .386 .model flat, stdcall .data score byte 67,89,90,56,29,80,34,65,90,98,100 count equ $-score scoreA dword 0 scoreB dword 0 scoreC dword 0 scoreD dword 0 scoreE dword 0 ..code start: mov ebx, score mov ecx, count call status ret status proc again: cmp byte ptr [ebx], 59 ja next inc scoreE jmp agaian1 next: cmp byte ptr [ebx], 69 ja next1 inc scoreD jmp again1 next1: cmp byte ptr [ebx], 79 ja next2 inc scoreC jmp again1 next2: cmp byte ptr [ebx], 89 ja next3 inc scoreB jmp again1 next3: inc scoreA again1: inc ebx loop again ret status endp end 13.编写一递归子程序,计算指数函数 X n 的值。 答: .386 .model flat, stdcall include \masm32\include\io32.inc .stack 256 .data N dword 3 X dword 3 result dword ? .code start: mov ebx,X入口参数:压入 X mov ebx, N push ebx c ;出口参数:弹出 N! WriteSDecDword r计算 N!的近子程序入口参数:压入 N出口参数:弹出 N! mov ebp,esp mov eax,[ebp+12] ;[ebp+12]=入口参数 N cmp eax,0 jne fact1 ;N≠0,跳转如果 N=0, =1 jmp fact2 fact1:N-1计算(N-1)!eax=(N-1)! mul word ptr [ebp+12]; N!=N*(N-1)! fact2: mov [ebp+12],eax ;将 N!存回[ebp+12] 恢复寄存器 pop eax ret fact endp end start 14.编写完整的程序用 ReadUDecDword 从键盘读入无符号双精度数,调用例题 7-14 子程序,转换成十进制字符串,用 WriteString 显示结果。 答:.386 .model flat, stdcall include \masm32\include\io32.inc .data string byte 10 dup(?) .code start: ReadUDecDword eax mov edi, offset string call UEaxdec WriteCrlf WriteString string ret UE入口参数:EAX=被转换的无符号数,EDI=字符串缓冲区首地址 ;出口参数:EDI=字符串缓冲区首地址 push e保存寄存器 xor edx, edx xor ecx, ecx mov ebx, 10;除数 10 a10:edx.eax÷余数进栈记录余数个数 xor edx, edx cmp eax,商是否为 0 jnz a10;商不是 0,跳转到 a10 a20:商为 0,从堆栈中取出余数 add al,'0';转换为字符 mov [edi],存入[edi]修改地址指针 loop a20; mov byte ptr [edi],0;字符串以 0 结尾 pop eax pop ecx pop edx ret Ueaxdec endp end start 15. 编写完整的程序用 ReadSDecDword 从键盘读入一个双精度数, 调用例题 7-15 子程 序,转换成十进制字符串,用 WriteString 显示结果。 .386 .model flat, stdcall include \masm32\include\io32.inc .data string byte 10 dup(?) .code start: ReadSDecDword eax mov edi, offset string call SEaxdec WriteCrlf WriteString string ret SE入口参数:EAX=被转换的有符号数,EDI=字符串缓冲区首地址 ;出口参数:EDI=字符串缓冲区首地址 push ed保存寄存器 test eax, 判断 eax 是否为负数是 0 和正数跳转到如果是负数,求绝对值 mov byte ptr [edi], '-' ;字符串的一个字符为'-'指向下一个字节 convert:call U转换为字符串恢复寄存器 pop ecx pop edx ret SEaxdec endp UE入口参数:EAX=被转换的无符号数,EDI=字符串缓冲区首地址 ;出口参数:EDI=字符串缓冲区首地址 push edx 保存寄存器 xor edx, edx xor ecx, ecx mov ebx, 10;除数 10 a10:edx.eax÷余数进栈记录余数个数 xor edx, edx cmp eax,商是否为 0 jnz a10;商不是 0,跳转到 a10 a20:商为 0,从堆栈中取出余数 add al,'0';转换为字符 mov [edi],存入[edi]修改地址指针 loop a20; mov byte ptr [edi],0;字符串以 0 结尾 pop eax pop ecx pop edx ret Ueaxdec endp end start 16.编写完整的程序用 ReadString 从键盘读入一个十进制字符串,调用例题 7-16 子程 序,转换成无符号 32 位数据,在 Windbg 中观察执行结果。 .386 .model flat, stdcall .data string byte '321',0 .code start: mov edi, offset string call StrToUDD ret StrToUDD十进制字符串转换为无符号 32 位数 ;入口参数:EDI=字符串缓冲区首地址,字符串以 0 结尾 ;出口参数:EAX=无符号的二进制数值 push edx push ebx xor eax, eax mov al,[edi];取出一个字符 cmp al,0 如果是 0,字符串跳转到 done and al, 0 如果不是 0,将字符转换为数据 0~9 mov ebx, eax inc edi read1: xor eax, eax mov al,[edi];取出一个字符 cmp al,0如果是 0,字符串跳转到 done and al, 0 如果不是 0,将字符转换为数据 0~9 shl ebx,1;ebx*2;利用移位指令,实现原来的数值乘 10:EBX←EBX×10 mov edx,edx=ebx*2 shl ebx,1;ebx*4 shl ebx,1;ebx*8 add ebx,ebx=ebx*10 add ebx,加上原来的数值乘以 10jmp read1 ;继续转换下一个字符 done: mov eax,设置出口参数 子程序返回 StrToUDD endp end start 17.编写完整的程序用 ReadString 从键盘读入一个十进制字符串,调用例题 7-17 子程 序,转换成无符号 32 位数据,在 Windbg 中观察执行结果。 .386 .model flat, stdcall include \masm32\include\io32.inc .data string byte 6 dup(?) .code start: ReadString string mov edi, offset string call StrToSDD WriteCrlf WriteSDecDword eax ret StrToUDD十进制字符串转换为无符号 32 位数 ;入口参数:EDI=字符串缓冲区首地址,字符串以 0 结尾 ;出口参数:EAX=无符号的二进制数值 push edx push ebx xor eax, eax mov al,[edi];取出一个字符 cmp al,0如果是 0,字符串跳转到 done and al, 0 如果不是 0,将字符转换为数据 0~9 mov ebx, eax inc edi read1: xor eax, eax mov al,[edi];取出一个字符 cmp al,0如果是 0,字符串跳转到 done and al, 0 如果不是 0,将字符转换为数据 0~9 shl ebx,1;ebx*2;利用移位指令,实现原来的数值乘 10:EBX←EBX×10 mov edx,edx=ebx*2 shl ebx,1;ebx*4 shl ebx,1;ebx*8 add ebx,ebx=ebx*10 add ebx,加上原来的数值乘以 10jmp read1 ;继续转换下一个字符 done: mov eax,设置出口参数 子程序返回 StrToUDD endp StrToSDD十进制字符串转换为无符号 32 位数 ;入口参数:EDI=字符串缓冲区首地址,字符串以 0 结尾 ;出口参数:EAX=有符号的二进制数值 push ebp mov ebp,ebp 指向栈顶 mov eax, 0局部变量 flag 记录数字的符号位,初始化为 0 mov al , [edi] cmp al, '-';判断字符串中第一个字符是否为'-'不是'-',直接转换 mov dword ptr [ebp-4],1;flag=1,符号位为 1指向数字字符 convert: call StrToUDD;转换为对应的 32 位无符号数 cmp dword ptr [ebp-4],1符号位为 0,表示是正数,跳转到 done 符号位为 1,表示是负数,求补 done: add esp, 4子程序返回 StrToSDD endp end start 18.编写子程序判断一个字符串是不是十进制字符串。如果是,EAX=0;如果不是, EAX=1。 答:isDecDigit proc uses edx,char:判断是否为十进制字符 ;入口参数 char=输入字符的 ASCII 码 ;出口参数 eax=0 是十进制字符,eax=1 不是十进制字符 xor al, al mov dl, char cmp dl,'0' jb L1 cmp dl,'9' jbe L2 L1: mov al, 1 L2: ret isDecDigit endp 19.重写 17 题,先用 18 题编写的子程序判断是否为合法十进制字符串,是则转换,不 是则提示非法信息退出程序。 提示: 子程序 StrToUDD 中先调用子程序 isDecDigit 判断是否为十进制字符, 是则转换, 不是则设置标志,返回。主程序中读取标志,如果不是十进制字符串提示错误信息返回。 20.用带参数的子程序定义方法重写例 7-14 至例 7-18。 答:UEaxdec proc x:dword, ad:ptr byte push edi push e保存寄存器 mov eax, x mov edi, ad xor edx, edx xor ecx, ecx mov ebx, 10;除数 10 a10:edx.eax÷余数进栈记录余数个数 xor edx, edx cmp eax,商是否为 0 jnz a10;商不是 0,跳转到 a10 a20:商为 0,从堆栈中取出余数 add al,'0';转换为字符 mov [edi],存入[edi]修改地址指针 loop a20; mov byte ptr [edi],0;字符串以 0 结尾 pop eax pop ecx pop edx pop edi ret Ueaxdec endp SEaxdec proc x :dword, ad :ptr byte push edi push edx push ecx push eax mov edi,保存寄存器test eax, 判断 eax 是否为负数是 0 和正数跳转到如果是负数,求绝对值 mov byte ptr [edi], '-' ;字符串的一个字符为'-'指向下一个字节 convert:invoke Ueaxdec,恢复寄存器 pop ecx pop edx pop edi ret SEaxdec endp StrToUDD proc ad: ptr byte;出口参数:EAX=无符号的二进制数值 push edi push edx push ebx mov edi, ad xor eax, eax mov al,[edi];取出一个字符 cmp al,0如果是 0,字符串跳转到 done and al, 0 如果不是 0,将字符转换为数据 0~9 mov ebx, eax inc edi read1: xor eax, eax mov al,[edi];取出一个字符 cmp al,0如果是 0,字符串跳转到 done and al, 0 如果不是 0,将字符转换为数据 0~9 shl ebx,1;ebx*2;利用移位指令,实现原来的数值乘 10:EBX←EBX×10 mov edx,edx=ebx*2 shl ebx,1;ebx*4 shl ebx,1;ebx*8 add ebx,ebx=ebx*10 add ebx,加上原来的数值乘以 10jmp read1 ;继续转换下一个字符 done: mov eax,设置出口参数 pop ebx 子程序返回 StrToUDD endp StrToSDD proc x:ptr byte;出口参数:EAX=有符号的二进制数值 push edi push ebp mov ebp,ebp 指向栈顶 mov eax, 0局部变量 flag 记录数字的符号位,初始化为 0 mov edi, x mov al , [edi] cmp al, '-';判断字符串中第一个字符是否为'-'不是'-',直接转换 mov dword ptr [ebp-4],1;flag=1,符号位为 1指向数字字符 convert: call StrToUDD;转换为对应的 32 位无符号数 cmp dword ptr [ebp-4],1符号位为 0,表示是正数,跳转到符号位为 1,表示是负数,求补 done: add esp, 4 子程序返回 21.将例 7-14 至例 7-17 建立一个子程序库。 答:\masm32\bin\ml /c /coff lt714.asm lt715.asm lt716.asm lt717.asm \masm32\bin\lib lt715.obj lt714.obj lt716.obj lt717.obj /out:io32.lib 22.将第六章的 17 题按照原要求设计成子程序,并建立子程序库。 略 23.伪指令 PUBLIC 和 EXTERN 表示什么意思?如何使用? 答:PUBLIC 伪指令用于说明某个变量或子程序等可以被别的模块使用;同时提供 EXTERN(MASM 5.x 是 EXTRN)伪指令用于说明某个变量或子程序是在别的模块中定义。 它们的格式为:PUBLIC 标识符 [,标识符...] ;定义标识符的模块使用 EXTERN 标识符:类型 [,标识符:类型...] ;调用标识符的模块使用24、伪指令 INVOKE 和 PROTO 如何使用? 答:INVOKE 伪指令的格式如下:INVOKE 子程序名[,参数,...]子程序调用伪指令自动创建调用子程序所需要的代码序列, 调用前将参数压入堆栈、 调 用后平衡堆栈。 PROTO 是一个子程序声明伪指令,用于事先声明子程序的结构。它的格式如下:子程序名 PROTO [调用距离] [语言类型] [,参数∶[类型]]...子程序说明伪指令 PROTO 语句中的各项必须与相应子程序定义伪指令 PROC 的各项一 致。 25、利用目标文件的连接开发程序时,应注意什么问题? 答: 创建多模块程序需要遵循以下步骤: (1)创建主程序模块,其中包含主程序的定义和程序入口的定义; (2)创建子程序模块,其中包含子程序的定义; (3)在调用子程序的模块中用 EXTERN 声明其他模块中定义的子程序和变量;也可以 用 PROTO 在调用子程序的模块中声明子程序,说明子程序的名字,参数和调用方式等; (4)在定义子程序的模块中用 PUBLIC 声明子程序或变量可以被其它模块使用;用 PROTO 伪指令声明子程序也有同样的作用; (5)最后,各个模块独立汇编,用连接程序将各个模块结合在一起。 模块间传递参数的基本方法与子程序间的参数传递方法一样。 少量参数可以用寄存器或 堆栈直接传送数据本身; 大量数据可以安排在缓冲区, 然后用寄存器或堆栈传送数据的存储 地址;还可以利用变量传递参数,但是要采用 public/extern 声明为公共(全局)变量。 用简化段定义格式时, 只要不同模块采用相同的存储模式, 就可以直接把子程序的定义 放在代码段中,数据的定义放在数据段中。 26、什么是子程序库,子程序库有什么作用,如何建立子程序库? 答:子程序库文件(.LIB)是子程序模块的集合,其中存放着各子程序的名称、目标代 码以及有关定位信息。子程序文件编写完成后,汇编形成目标文件;然后利用库管理工具程 序 LIB.EXE,把子程序目标模块逐一加入到库中。LIB 命令的格式是:LIB 子程序目标文件名 /out:库文件名 习题81. 分别编写实模式应用程序和 32 位应用程序从键盘输入一个字符串, 先将它原样显示 一遍;然后将其中的小写字母转换为大写显示,再将其中的大写字母转换为小写显示,最后 将其中的大小写字母互换显示。显示字符串,大写转换、小写转换和大小写互换功能写成子 程序。 (1)编写一个完整的源程序完成题目要求。 (2)把子程序单独汇编,用目标文件连接的方法完成题目要求。 (3)把子程序加入到一个子程序库中,用子程序库调入的方法完成题目要求。 参考例 8-18 和例 8-19。 2.什么是端口,处理器使用什么指令与外设进行数据交换,需要通过什么电路实现? 答:I/O 接口是主机与外设之间协调两者数据传送的逻辑电路,在输入输出程序中,各 种寄存器以 I/O 地址(端口)体现;三种寄存器对应地分别被称为数据端口、控制端口和状 态端口。外设通过 I/O 端口与主机交换信息。 3.什么是 I/O 位图? 答: 在保护模式下, 任务状态段中设置有 I/O 许可位图。 许可位图就是一个二进制位串。 I/O 位串中的每一位对应一个 I/O 地址,位串的 D0 位对应 I/O 地址 0,位串的 Dn 位对应 I/O 地 址 n。如果位串的 Di 位为 0,则 I/O 地址 i 可以由任意特权级的程序访问,没有限制;如果 位串的 Di 位为 1,则 I/O 地址 i 只能由在 IOPL 特权级或更高特权级运行的程序访问。如果 特权级低于 IOPL 的程序访问许可位为 1 的 I/O 端口将会引起异常。 4.PC 机中扬声器的声音频率是可调的,参考如下子程序。;发音频率设置子程序,入口参数:AX=1.1÷发音频率 speaker proc push ax mov al,0b6h out 43h,al pop ax out 42h,al mov al,ah out 42h,写入低 8 位定时值 ;注:42h 是定时器 2 的数据端口 ;写入高 8 位定时值 ;(由于系统已设置好,这 4 条指令也可以不要) ;设置定时器 2 工作方式 ;注:43h 是定时器 2 的控制端口利用扬声器控制原理,编写一个实模式的简易乐器程序。 当按下 1~8 数字键时,分别发出连续的中音 1~7 和高音 i(对应频率依次为 524Hz、 588Hz、660Hz、698Hz、784Hz、880Hz、988Hz 和 1048Hz); 当按下其他键时暂停发音; 当按下 ESC 键(ASCII 码为 1BH),程序返回操作系统。 参考例题 8-5 和例 8-10 6.编写一个 32 位应用程序完成与上题相同的功能。(提示:使用本书提供的 GIVEIO.BAT 和 CHECKIO.INC) 7.利用第六章和第七章设计的子程序,编写 32 位子程序完成下面的功能。 (1)输入一个字节的无符号十进制数到 AL 寄存器; (2)输入一个字节的有符号十进制数到 AL 寄存器; (3)输入一个字节的十六进制数到 AL 寄存器; (4)输入一个字节的二进制数到 AL 寄存器; (5)将 AL 寄存器的内容以二进制的形式显示; (6)将 AL 寄存器的内容以十六进制的形式显示; (7)将 AL 寄存器的内容以无符号十进制的形式显示; (8)将 AL 寄存器的内容以有符号十进制的形式显示。 参考例题 8-15 和 8-16 编写显示和输入字符串的子程序,参考习题 7 的 20 题,编写字 符串与数值之间的转换。 8.利用第 6 章和第 7 章设计的子程序,编写实模式子程序完成下面的功能。 (1)输入一个字节的无符号十进制数到 AL 寄存器; (2)输入一个字节的有符号十进制数到 AL 寄存器; (3)输入一个字节的十六进制数到 AL 寄存器; (4)输入一个字节的二进制数到 AL 寄存器; (5)将 AL 寄存器的内容以二进制的形式显示; (6)将 AL 寄存器的内容以十六进制的形式显示; (7)将 AL 寄存器的内容以无符号十进制的形式显示; (8)将 AL 寄存器的内容以有符号十进制的形式显示。 9.将 AL 寄存器改写成 AX 和 EAX 寄存器重写以上两题。 10.利用 7、8、9 题设计的子程序建立实模式的子程序库 XTIO16.LIB 和 32 位子程序 库 XTIO32.LIB,并设计测试程序测试子程序实现功能的正确性 \masm32\bin\ml /c /coff *.asm \masm32\bin\lib *.obj /out:xtio32.lib习题91.假设有下列数据定义: source byte ?abcdefghijklmnopqrst? destination byte 20 dup(?) 请用串操作指令实现以下功能: (1)把 source 开始的字符串按从左到右的次序依次传送到 destination 存储区; 参考答案: .code mov ecx, 20 mov esi, offset source mov edi, offset destination cld rep movsb (2)把 source 开始的字符串按从右到左的次序依次传送到 destination 存储区; 参考答案: .code mov ecx, 20 mov esi, offset source+19 mov edi, offset destination+19 std rep movsb 2.编写程序,将 buf 开始的 100000 个字节单元清零。 参考答案: .code mov ecx, 100000 mov edi, offset buf mov al, 0 cld rep stosb 3.编写程序将 string 开始的 100B 长的字符串中的‘$’符号换为空格符。 参考答案: .code mov ecx, 100 mov esi, offset string cld again:lodsb cmp al, ?$? jne next mov byte ptr [edi-1],20h next: cmp ecx, 0 jne again 4.编写程序统计习题 3 的字符串中‘*’符号的个数。 参考答案: .code mov ecx, 100 xor edx, edx mov esi, offset string cld again:lodsb cmp al, ?*? jne next inc edx next: cmp ecx, 0 jne again 5.编写程序设有一 1000 个元素的字数组存放在 array 开始的存储区中。现将该数组进 行压缩,删除其中的 0 元素,非 0 元素的顺序不变。参考答案: .data string word 3,20,0,9,8,78 ;假设一个字数组 ;元素个数count equ ($-string)/ 2 .code start: mov esi,offset string mov ecx, countcld outlp: cmp ecx , 0jz done again: loadw cmp ax,0 jnz outlp mov edi,esi push ecx;外循环,先判断后循环;为 0 结束 ;检测是否为 0 ;不是 0 继续循环 ;是 0,进入剔除 0 分支,该分支是循环程序段inlp:;下一个字符的位置;字符前移一个位置 ;内循环,先循环后判断 ;字符串没有结束继续移字符 ;字符移动完毕,继续判断是否为空格 ;继续对后续字符进行判断处理mov ax,[edi] mov [edi-1],ax dec ecx jnz inlp pop ecx jmp again next:6. 编写程序比较两个字符串 str1 和 str2, 若相同, ‘same!’ 否则, ‘no same!’ 显示 ; 显示 。 字符串 str1 和 str2 长度可能不一样。 参考答案:mov esi,offset string1 push esi call strlen mov edi,offset string2 push edi call strlen mov ecx,count cld again: cmpsb jnz unmat dec ecx jnz again clc jmp output unmat: output: ;进行下一个字符的比较 ;字符串相等,设置 CF=0 ;转向输出结果标记 ;比较两个字符 ;出现不同的字符,转移到 unmat,设置 CF=17.编写程序逆序拷贝字符串。 参考答案: .code mov ecx, 20 mov esi, offset source+count mov edi, offset destination+count std rep movsb 8.编写程序连接两个字符串。 参考答案: .data src1 byte “dsfhsdf”,0 count1 equ $-src1 src2 byte “dhfjdfg”,0 count2 equ $-src2 dest byte 100 dup(?) .code mov esi, offset src1 cld mov ecx, count1-1 mov edi, offset dest rep movsb mov esi, offset src2 mov ecx, count2 rep movsb 9.编写程序在字符串中去除指定字符。 参考 lt621 和习题 5习题 101.宏是如何定义、调用和展开的? 答: 宏定义由一对宏汇编伪指令 MACRO / ENDM 来完成,其格式如下:宏名 MACRO [形参表] 宏定义体 ENDM宏定义之后就可以在程序中调用它。它的格式为:宏名 [实参表]可见, 宏调用的格式同一般指令一样, 在使用宏指令的位置写下宏名, 后跟实体参数 (实 元);如果有多个参数,应按形参顺序填入实参,也用逗号分隔。注意宏调用一定要遵循先 定义后调用的原则。 在汇编时, 由汇编程序对宏调用进行扩展。 所谓宏扩展是指对应的代码序列替代宏指令 名,并用相应位置的实参替换形参。 2.宏定义中的形式参数有什么特点,它是如何进行形参和实参结合的? 答:实参与形参的个数可以不等,多余的实参不予考虑,缺少对应实参的形参做“空” 处理(以空格取代);另外汇编程序不对实参和形参进行类型检查,取代时完全是字符串的 替代,至于宏展开后是否有效则由汇编程序在翻译时进行语法检查。 宏的参数功能强大,既可以无参数,又可以带有一个或多个参数;而且参数的形式非常 灵活,可以是常数、变量、存储单元、指令(操作码)或它们的一部分,也可以是表达式。 3.宏结构和子程序在应用中有什么不同,如何选择采用何种结构? 答:(1)宏调用在汇编时进行程序语句的展开,不需要返回;它仅是源程序级的简化, 并不减小目标程序,因此执行速度没有改变。子程序调用在执行时由 CALL 指令转向子程 序体,子程序需要执行 RET 指令返回;它还是目标程序级的简化,形成的目标代码较短。 但是,子程序需要利用堆栈保存和恢复转移地址、寄存器等,要占用一定的时空开销;特别 是当子程序较短时,这种额外开销所占比例较大。 (2)宏调用的参数通过形参、实参结合实现传递,简捷直观、灵活多变。子程序需要 利用寄存器、存储单元或堆栈等传递参数。对宏调用来说,参数传递错误通常是语法错误, 会由汇编程序发现; 而对子程序来说, 参数传递错误通常反映为逻辑或运行错误, 不易排除。 除此之外, 宏与子程序都还具有各自的特点, 程序员应该根据具体问题选择使用那种方 法。 通常, 当程序段较短或要求较快执行时, 应选用宏; 当程序段较长或为减小目标代码时, 要选用子程序。 4.宏汇编、重复汇编与条件汇编有什么异同? 答: 宏是具有宏名的一段汇编语句序列, 通常与宏配合使用的伪指令还有重复汇编和条 件汇编,统称为宏结构 程序中有时需要连续地重复编写一段相同或者基本相同的语句, 这时可以用重复汇编伪 指令来完成。重复汇编定义的程序段也是在汇编时展开,并且经常与宏定义配合使用。 条件汇编伪指令根据某种条件确定是否汇编某段语句序列, 可以提高汇编效率, 它与高 级语言的条件编译命令类似。 5.对于例题 10-3 的宏定义 shrot,对应如下宏指令的宏展开是什么?shrot word ptr [bx],4,ror答:push ecx mov cl,4 ror word ptr [bx],cl pop ecx6.定义一个宏 logical,用它代表 4 条逻辑运算指令:and/or/xor/test,注意需要利用 3 个形式参数,并给一个宏调用以及对应宏展开的例子。答:logical macro src, dest,opcode mov eax, src opcode eax, dest mov dest, eax endm7.必要时做一点修改,使在上一习题定义的宏 logical 能够把 neg 指令包括进去,也请 给一个使用 neg 指令的宏调用以及对应宏展开的例子。答:logical macro src, dest,opcode ifidni opcode, &neg&neg src mov dest, src exmit endifmov eax, src opcode eax, dest mov dest, eax endm8. 编写一个宏指令 move doprnd,soprnd, 它实现任意寻址方式的字量源操作数送到目的 操作数,包括存储单元到存储单元的传送功能。 答:答:move macro src, destpush src pop destendm9.定义一个宏 movestr strN,dstr,sstr,它将 strN 个字符从一个字符区 sstr 传送到另一个 字符区 dstr。答:movestr macro strN, dstr, sstrpush ecx push esi push edi mov ecx, strN lea esi, sstr lea edi, dstr rep movsbpop edipop esi pop ecxendm10.给出宏定义如下:DIF macro X,Y MOV AX,X SUB AX,Y endm ABSDIF macro V1,V2,V3 LOCAL CONT push AX DIF V1,V2 CMP AX,0 JGE CONT NEG AX CONT: MOV V3,AX pop AX endm试展开以下宏调用:① 参考答案: ABSDIF P1,P2,DISTANCE push AX MOV AX,P1 SUB AX,P2 CMP AX,0 JGE ??0000 NEG AX ??0000: MOV DISTANCE,AX pop AX② ABSDIF [BX],[SI],[DI] 参考答案: push AX MOV AX,[BX] SUB AX,[SI] CMP AX,0 JGE ??0000 NEG AX ??0000: MOV [DI],AX pop AX11.利用重复汇编方法定义一个数据区,数据区有 100 个双字,每个双字的高字部分依 次是 2,4,6,?,200,低字部分都是 0。 参考答案:DA1 = 2 Aztable equ this byte repeat 100 dword DA1 DA1 = DA1 +2AZtable 用于为字符串指明首地址12.利用宏结构完成以下功能:如果名为 byteX 的数据大于 5 时,指令“ADD AX,AX” 将汇编 10 次,否则什么也不汇编。 参考答案: xt1012 macro byteX if byteX gt 5 repeat 10 add ax, ax endm endif endm 13. 用宏结构实现宏指令 FINSUM, 它比较两个数 wordX 和 wordY, wordX & wordY, 若 则执行 SUM←wordX+2×wordY,否则执行 SUM←2×wordX+wordY。\\ 参考答案: FINSUM macro wordX, wordy if wordX gt wordy shl wordy, 1 add wordX, wordy mov SUM, wordX else shl wordX, 1 add wordX, wordy mov SUM, wordX endif endm 14.用宏完成大写转换为小写字母。 答案: convert macro data mov al, data or al, 20h endm 15.什么是宏库,它有什么作用,如何利用它? 答:如果希望宏在不同的源程序中使用,经常把宏放在一个宏库文件中,在需要使用宏的地 方用 INCLUDE 语句包含这个文件,习题1.什么是混合编程?汇编语言与 CMC++语言的混合编程有两种方法?各有什么特 点? 答:组合多种程序设计语言,通过相互调用、参数传递、共享数据结构和数据信息而形 成程序的过程就是混合编程。 汇编语言与 CMC++语言的混合编程有两种方法:嵌入式汇编和模块连接 嵌入式汇编的功能, 不需要额外的编译器和连接器, 可以在 C++源程序中直接插入汇编 语言指令的语句。嵌入式汇编语言指令可以直接访问 C++语言程序中定义的常量、变量、函 数,而不必考虑二者之间的接口;这样,可以避免汇编语言与 C++语言间复杂的接口问题, 从而提高程序设计的效率。 当汇编语言实现的功能比较复杂时,采用嵌入式语句就不容易管理和调试,这时可将 C++程序和汇编程序分别进行编程,形成各自的 OBJ 模块,再进行模块连接生成 EXE 程序。 模块连接方式是不同程序设计语言之间混合编程经常使用的方法。 2.Visual C++支持的汇编语言指令集是什么? 答:嵌入式汇编代码支持 80486 的全部指令系统。Visual C++ 5.0M6.0 还支持 MMX 指 令集。对于还不能支持的指令,Visual C++提供了_emit 伪指令进行扩展。 3.利用模块连接方式进行混合编程,需要注意哪些方面的约定? 答:命名约定、声明约定、寄存器使用约定、存储模式约定,参数传递约定 4.总结一下 C 调用汇编语言程序的参数传递原则。 答:C/C++语言中不论采用何种调用规范,传送的参数形式都是“传值” (by Value) , 但传递数组不是传值而是传址(因为数组名表示的是第一个元素的地址) 。参数“传址” (by Reference)应利用指针数据类型。通过堆栈传递。 参数返回时,对于小于等于 32 位的数据扩展为 32 位,存放在 EAX 寄存器中返回;4~ 8 字节的返回值存放在 EDX.EAX 寄存器对中返回;更大字节数据则将它们的地址指针存放 在 EAX 中返回。 5.如下有一个简单的 C 语言源程序:main() { sum(3,4); } sum(int x,int y) { sum=x+y; return(sum); } /* 定义一个局部变量 */ /* 求和 */ /* 返回和值 */ /* 求两数之和的函数,x 和 y 是入口参数 */首先,用嵌入汇编方法实现加法函数 sum,上机调试通过。 参考答案: #include &iostream.h& extern &C& int sum(int,int); void main() { cout&&sum(3,4)&& } int sum(int x,int y) { __asm{ mov eax, x add eax, y } } 然后,编写一个汇编语言子程序实现加法函数 sum,并用模块连接方式实现与 C 语言 主函数混合编程,上机调试通过。 参考答案: //c++程序 #include &iostream.h& extern &C& int _cdecl sum(int,int); void main() { cout&&sum(3,4)&&} ; 汇编程序 .386 .model flat, stdcall public sum .code sum proc c x:dword , y:dword mov eax, x add eax, y ret sum endp end 最后,生成上述 C 语言源程序对应的汇编格式源程序,并对比你采用的两个实现方法。 6.在 C 程序中输入两个整数,然后调用汇编子程序对这两个数求积,在主程序中打印 计算结果。编程并上机调试通过。 参考答案: //c++程序 #include &iostream.h& extern &C& int _cdecl multiply(int,int); void main() { cout&&multiply(3,4)&&} ; 汇编程序 .386 .model flat, stdcall public multiply .code multiply proc c x:dword , y:dword mov eax, x imul y ret multiply endp end 7.编写程序,在汇编程序中初始化 varA=12、varB=6,调用 C 语言的子程序求积并 打印计算结果。编程并上机调试通过。 参考答案: //c++程序 #include &iostream.h& extern &C& int multiply(int,int); extern &C& int init(); void main() { cout&&init()&&} multiply(int x, int y) { return x*y; } ; 汇编程序 .386 .model flat, stdcall public init multiply proto c x:dword, y:dword .data varA dword ? varB dword ? .code init proc c mov varA, 12 mov varB,6 push varA push varB call multiply add esp, 8 ret init endp end 8.阅读如下混合编程的源程序,说明程序运行结果,并上机验证。 /* C 语言程序 */ #include &stdio.h& extern &C& void _stdcall callasm(void); extern &C& int _add(int x,int y); void main () { callasm(); } int _add(int x,int y) { printf(&In the _add(x,y):\n&); printf(&x = %d\n&,x); printf(&y = %d\n&,y); printf(&%d+%d=%d\n&,x,y,x+y); return(x+y); } ; 汇编语言程序 .386 .model flat,stdcall public callasm extern _add:near32 .data _A dword 2 _B dword 6 _C dword ? .code public callasm callasm proc stdcall push _B push _A call _add add esp,8 mov _C,eax ret callasm endp end 答:In the _add(x,y): x=2 y=6 2+6=8 9.将排序子程序改写成 C 语言的嵌入式汇编函数;然后编写一个 C 语言主程序,提供 待排序的数据和显示排序后的结果。 参考答案: #include &iostream.h& void paixu(short int* array,int N); void main() { short int array[]={ 10,20,-20,0,30,-45,50,-60,7,98}; int count=10; paixu(array,count); for (int i=0; i& i++) cout&&array[i]&&& &; cout&& } void paixu(short int* array,int N) { __asm{ mov ecx, N dec ecx mov edi,设置外循环次数,元素个数减 1 lea ebx,ebx=数组 array 首地址 again1:mov ecx,设置内层循环次数 mov esi, 1 mov al,[ebx] again2:cmp al,[ebx+esi] ;与 AL 比较 jle next xchg al, [ebx+esi] ;如果大于,则交换 next: inc esi loop again2 mov [ebx], al inc ebx dec edi jnz again1;最大值存入[ebx] ;修改地址指针 ;外层循环次数减 1 ;如果不为 0,继续比较} } 10.将排序子程序改写成可供 C 语言调用的模块;然后编写一个 C 语言主程序,提供 待排序的数据和显示排序后的结果。 参考答案: //C++程序 #include &iostream.h& extern &C& void paixu(short int* array,int N); void main() { short int array[]={ 10,20,-20,0,30,-45,50,-60,7,98}; int count=10; paixu(array,count); for (int i=0; i& i++) cout&&array[i]&&& &; cout&& } ;汇编程序 .386 .model flat, stdcall .code paixu proc c array:ptr dword, N : dword mov ecx, N dec ecx mov edi,设置外循环次数,元素个数减 1 lea ebx,ebx=数组 array 首地址 again1:mov ecx,设置内层循环次数 mov esi, 1 mov al,[ebx] again2:cmp al,[ebx+esi] ;与 AL 比较 jle next xchg al, [ebx+esi] ;如果大于,则交换 next: inc esi loop mov inc dec jnzagain2 [ebx], al ebx edi again1;最大值存入[ebx] ;修改地址指针 ;外层循环次数减 1 ;如果不为 0,继续比较ret paixu endp end 11.说明 Visual C++嵌入汇编语言指令的形式。 答:_ _asm{ ;汇编指令 } 12.说明如下程序的输出结果,然后上机验证。// C++程序: #include &iostream.h& extern &C& { void MLSub(char *,short *,long *); } char chararray[4] = &abc&; short shortarray[3] = {1,2,3}; long longarray[3] = {,32770}; void main(void) { cout&&chararray&& cout&&shortarray[0]&&shortarray[1]&&shortarray[2]&& cout&&longarray[0]&&longarray[1]&&longarray[2]&& MLSub (chararray,shortarray,longarray); cout&&chararray&& cout&&shortarray[0]&&shortarray[1]&&shortarray[2]&& cout&&longarray[0]&&longarray[1]&&longarray[2]&& } ; 汇编语言程序:XT.ASM .386 .model flat,C .code MLSub proc uses esi, \ arraychar:PTR,arrayshort:PTR,arraylong:PTR mov esi,arraychar mov BYTE PTR [esi],&x& mov BYTE PTR [esi+1],&y& mov BYTE PTR [esi+2],&z& mov esi, add WORD PTR [esi],7 add WORD PTR [esi+2],7 add WORD PTR [esi+4],7 mov esi,arraylong inc DWORD PTR [esi] inc DWORD PTR [esi+4] inc DWORD PTR [esi+8] ret MLSub endp End答案:abc 123 770 xyz . 编写识别 CPU 的汇编语言过程, Visual C++6.0 调用的形式, 供 然后编写一个 Visual C++主程序,并上机调试通过。 参考答案: ;xt1113b.asm .586 .model flat,stdcall public get_cpu_type get_cpu_type proc , stdcall push eax mov eax , 1 返回 eax=特征标志字 mov eax, edx and eax, 0f00h pop eax ret get_cpu_type endp end //xt1113.cpp #include &iostream.h& extern “C” int _stdcall get_cpu_type(); main() { unsign long cpu_ cpu_type = get_cpu_type () ; switch (cpu_type) { case 0: cout&&””&& case 2: cout&&”80286”&& case 3: cout&&”80386”&& case 4: cout&&”80486”&& case 5: cout&&”Pentium”&& case 6: cout&&”Pentium Pro”&& }
更多搜索:
All rights reserved Powered by
文档资料库内容来自网络,如有侵犯请联系客服。

我要回帖

更多关于 php数组题目 的文章

 

随机推荐