汇编学习总结
因快期末考啦。。。下面是我个人对汇编学习的复习 大家可以忽略。。。。。。
汇编大多是指汇编语言,汇编程序。把汇编语言翻译成机器语言的过程称为汇编。在汇编语言中,用助记符(Memoni)代替操作码,用地址符号(Symbol)或标号(Label)代替地址码。这样用符号代替机器语言的二进制码,就把机器语言变成了汇编语言。于是汇编语言亦称为符号语言。用汇编语言编写的程序,机器不能直接识别,要由一种程序将汇编语言翻译成机器语言,这种起翻译作用的程序叫汇编程序,汇编程序是系统软件中语言处理的系统软件。
随着现代软件系统越来越庞大复杂,大量经过了封装的高级语言如C/C++,Pascal/Object Pascal也应运而生。这些新的语言使得程序员在开发过程中能够更简单,更有效率,使软件开发人员得以应付快速的软件开发的要求。而汇编语言由于其复杂性使得其适用领域逐步减小。但这并不意味着汇编已无用武之地。由于汇编更接近机器语言,能够直接对硬件进行操作,生成的程序与其他的语言相比具有更高的运行速度,占用更小的内存,因此在一些对于时效性要求很高的程序、许多大型程序的核心模块以及工业控制方面大量应用。
题目一:输入输出
键盘输入2个实数,然后按相反顺序输出这2个实数。
运行后若输入:3.3 4.45
则结果输出:4.45 3.3
运行后若输入:1.35 2.4
则结果输出:2.4 1.35
.386 ;选择的处理器
.model flat, stdcall
option casemap:none ;指明标识符大小写敏感
include kernel32.inc ;要引用的头文件
includelib kernel32.lib ;要引用的库文件
includelib msvcrt.lib ;引用C库文件
scanf PROTO C:DWORD,:vararg ;C语言scanf函数原型声明
printf PROTO C:DWORD,:vararg;C语言printf函数原型声明
.data ;⑤数据段
;*【*/
a qword ?
b qword ?
fmt byte '%lf %lf',0
fmto byte '%g %g',0
.code
start:
invoke scanf,addr fmt,addr a,addr b
invoke printf,addr fmto,b,a
;*】*/
invoke ExitProcess,0 ;退出进程,返回值为0
end start
2、定义结构体商品,含编号、品名、单价、数量,输入一个商品信息求其金额并输出(按“%g”格式输出)。
若运行后输入:S001 小刀 4.5 2
则运行结果输出:编号:S001,品名:小刀,单价:4.5,数量:2,金额:9
请在;*【*/和;*】*/之间编写程序。
/***源程序asm***/
.386
.model flat, stdcall
option casemap :none
include kernel32.inc
includelib kernel32.lib
includelib msvcrt.lib ;引用C库文件
printf PROTO C:ptr sbyte,:vararg ;C语言printf函数原型声明
scanf PROTO C:ptr sbyte,:vararg ;C语言scanf函数原型声明
;*【*/
.data
jin QWORD 9.0
fat BYTE '%s %s %lf %d',0;
outfat BYTE '编号:%s,品名:%s,单价:%g,数量:%d,金额:%g',0;
Show struct
id BYTE 14 DUP(?)
n BYTE 20 DUP(?)
dj QWORD 4.0
num DWORD 4
Show ends
s Show <>
.code
start:
invoke scanf,ADDR fat,ADDR s.id,ADDR s.n,ADDR s.dj,ADDR s.num;
FLD s.dj
FiMUL s.num
FSTP jin
invoke printf,ADDR outfat ,ADDR s.id,ADDR s.n,s.dj,s.num,jin;
invoke ExitProcess,0 ;退出进程,返回值为0
end start
;*】*/
题目二:加减乘除
1、输入两个小写字母,然后输出其相应的大写字母。
运行后输入:
a b
则结果输出:
A B
请在;*【*/和;*】*/之间编写程序。
.386 ;选择的处理器
.model flat, stdcall
option casemap:none ;指明标识符大小写敏感
include kernel32.inc ;要引用的头文件
includelib kernel32.lib ;要引用的库文件
includelib msvcrt.lib ;引用C库文件
scanf PROTO C:DWORD,:vararg ;C语言scanf函数原型声明
printf PROTO C:DWORD,:vararg;C语言printf函数原型声明
.data ;⑤数据段
;*【*/
a BYTE ?
b BYTE ?
d BYTE ?
e BYTE ?
fmt BYTE '%c %c',0
fmto BYTE '%c %c',0
.code
start:
invoke scanf,ADDR fmt ,ADDR a,ADDR b;
MOV EAX, DWORD PTR a
SUB EAX, 32
MOV DWORD PTR d, EAX
MOV EAX, DWORD PTR b
SUB EAX, 32
MOV DWORD PTR e, EAX
invoke printf,ADDR fmto,DWORD PTR d,DWORD PTR e;
;*】*/
invoke ExitProcess,0 ;退出进程,返回值为0
end start
题目三:函数调用
1、键盘输入实数a和整数n的值,求a*2n的值:
运行后若输入:1.5 3
则结果输出:1.5*2^3=12
请在;*【*/和;*】*/之间编写程序。
/***源程序asm***/
;*【*/
.386
.model flat,stdcall
option casemap:none
include kernel32.inc
includelib kernel32.lib
includelib msvcrt.lib
scanf PROTO C:DWORD,:vararg
printf PROTO C:DWORD,:vararg
.data
a QWORD ?
n DWORD ?
z QWORD ?
fmt BYTE '%lf %d',0
fmt2 BYTE '%g*2^%d=%g',0
.code
start:
invoke scanf,ADDR fmt,ADDR a,ADDR n
FILD n
FLD a
FSCALE
FSTP z
invoke printf,ADDR fmt2,a,n,z
invoke ExitProcess,0
end start
;*】*/
2、已知机器人当前的位置为(0,0),若该机器人的下一个位置为(x,y),请计算该机器人前进的方向角(角度)。输入x和y值,用反正切函数指令(FPATAN)求角度。
运行后若输入:1.0 1.0
则结果输出:45
运行后若输入:-1.0 1.0
则结果输出:135
运行后若输入:1.0 -1.0
则结果输出:-45
运行后若输入:-1.0 -1.0
则结果输出:-135
请在;*【*/和;*】*/之间编写程序。
;*【*/
.386
.model flat,stdcall
option casemap:none
include kernel32.inc
includelib kernel32.lib
includelib msvcrt.lib
scanf PROTO C:DWORD,:vararg
printf PROTO C:DWORD,:vararg
.data
x QWORD 180.0
y QWORD 3.1415926
a QWORD ?
b QWORD ?
z QWORD ?
s QWORD ?
d QWORD ?
fmt BYTE '%lf %lf',0
fmt2 BYTE '%g',0
.code
start:
invoke scanf,ADDR fmt,ADDR a,ADDR b
FLD b
FLD a
FPATAN
FSTP z
FLD z
FMUL x
FSTP s
FLD s
FDIV y
FSTP d
invoke printf,ADDR fmt2,d
invoke ExitProcess,0
end start
;*】*/
3、键盘输入实数a和整数n的值,求a*2n的值:
运行后若输入:1.5 3
则结果输出:1.5*2^3=12
请在;*【*/和;*】*/之间编写程序。
/***源程序asm***/
;*【*/
.386
.model flat,stdcall
option casemap:none
include kernel32.inc
includelib kernel32.lib
includelib msvcrt.lib
scanf PROTO C:DWORD,:vararg
printf PROTO C:DWORD,:vararg
.data
a QWORD ?
n DWORD ?
z QWORD ?
fmt BYTE '%lf %d',0
fmt2 BYTE '%g*2^%d=%g',0
.code
start:
invoke scanf,ADDR fmt,ADDR a,ADDR n
FILD n
FLD a
FSCALE
FSTP z
invoke printf,ADDR fmt2,a,n,z
invoke ExitProcess,0
end start
;*】*/
题目四:选择结构
1、编写一段程序,完成下面计算公式,其中:变量x和y都是REAL8类型,结果保留2位小数。
运行后若输入:-2.0
则结果输出:-0.91
运行后若输入:0.52
则结果输出:1.04
运行后若输入:2.0
则结果输出:-0.42
请在;*【*/和;*】*/之间编写程序。
/***源程序asm***/
;*【*/
.386 ;选择的处理器
.model flat, stdcall ;存储模型,Win32程序只能用平展(flat)模型
option casemap:none ;指明标识符大小写敏感
include kernel32.inc ;要引用的头文件
includelib kernel32.lib ;要引用的库文件
includelib msvcrt.lib ;引用C库文件
scanf PROTO C:DWORD,:vararg ;C语言scanf函数原型声明
printf PROTO C:DWORD,:vararg ;C语言printf函数原型声明
.data ;⑤数据段
x QWORD ?
a QWORD -1.0
b QWORD 1.0
d QWORD 2.0
y QWORD ?
intfmt BYTE '%lf',0
outfmt BYTE '%.2lf',0
.code
start:
invoke scanf,addr intfmt,addr x
FEQU=40H
FLESS=1
FLD x
FCOMP a
fnstsw ax
.IF (AH&FLESS)
FLD x
FSIN
FSTP y
invoke printf,addr outfmt,y
.ELSE
FLD x
FCOMP b
fnstsw ax
.IF AH & (FLESS or FEQU)
FLD x
FMUL d
FSTP y
invoke printf,addr outfmt,y
.ELSE
FLD x
FCOS
FSTP y
invoke printf,addr outfmt,y
.ENDIF
.ENDIF
invoke ExitProcess,0 ;⑨退出进程,返回值为0
end start ;⑩指明程序入口点
;*】*/
2、用.IF….ELSEIF伪指令实现输入一个分数(0~100的整数),输出相应的成绩等级。分数与成绩等级对应关系分别为90~100分为优秀,80~89为良好,70~79为中,60~69为及格,0~59为不及格。
运行后若输入:95
则结果输出:优秀
运行后若输入:86
则结果输出:良好
运行后若输入:73
则结果输出:中
运行后若输入:66
则结果输出:及格
运行后若输入:53
则结果输出:不及格
请在;*【*/和;*】*/之间编写程序。
.386 ;选择的处理器
.model flat, stdcall ;存储模型,Win32程序只能用平展(flat)模型
option casemap:none ;指明标识符大小写敏感
include kernel32.inc ;要引用的头文件
includelib kernel32.lib ;要引用的库文件
includelib msvcrt.lib ;引用C库文件
scanf PROTO C:DWORD,:vararg ;C语言scanf函数原型声明
printf PROTO C:DWORD,:vararg ;C语言printf函数原型声明
.data ;⑤数据段
;*【*/
x DWORD ?
s BYTE '优秀',0
s1 BYTE '良好',0
s2 BYTE '中',0
s3 BYTE '及格',0
s4 BYTE '不及格',0
fmt BYTE '%d',0
fmto BYTE '%s',0
.code
start:
invoke scanf,ADDR fmt,ADDR x;
.IF x>=90
invoke printf,ADDR fmto,ADDR s;
.ELSEIF x>=80&&x<=89
invoke printf,ADDR fmto,ADDR s1;
.ELSEIF x>=70&&x<=79
invoke printf,ADDR fmto,ADDR s2;
.ELSEIF x>=60&&x<=69
invoke printf,ADDR fmto,ADDR s3;
.ELSEIF x<60
invoke printf,ADDR fmto,ADDR s4;
.ENDIF
;*】*/
invoke ExitProcess,0 ;⑨退出进程,返回值为0
end start ;⑩指明程序入口点start
题目五:循环结构
1、输入若干整数,统计正数与负数和。
运行后若输入:1 -2 3 -4
则结果输出:正数和为:4 负数和为:-6
请在;*【*/和;*】*/之间编写程序。
/***源程序asm***/
.386 ;选择的处理器
.model flat, stdcall ;存储模型,Win32程序只能用平展(flat)模型
option casemap:none ;指明标识符大小写敏感
includelib msvcrt.lib ;引用C库文件
scanf PROTO C:DWORD,:vararg ;C语言scanf函数原型声明
printf PROTO C:DWORD,:vararg ;C语言printf函数原型声明
.data ;⑤数据段
szFmt BYTE '正数和为:%d 负数和为:%d',0
;*【*/
a sdword ?
Infmt byte '%d',0
.code
start:
invoke scanf,addr Infmt,addr a
mov esi,0
mov edi,0
.while eax==1
.if a>0
add esi,a
.else
add edi,a
.endif
invoke scanf,addr Infmt,addr a
.endw
invoke printf,addr szFmt,esi,edi
ret
;*】*/
end start
2、键盘输入若干对实数x、y,求各对实数乘积和。
运行后若输入:
2.5 2
1.5 4
2.2 2
则结果输出:
15.4
请在;*【*/和;*】*/之间编写程序。
;*【*/
.386
.model flat, stdcall
include kernel32.inc
includelib kernel32.lib
includelib msvcrt.lib ;引用C库文件
printf PROTO C:ptr sbyte,:vararg ;C语言printf函数原型声明
scanf PROTO C:ptr sbyte,:vararg ;C语言scanf函数原型声明
option casemap :none
.data
x qword ?
y qword ?
s qword 0.0
z qword ?
Infmt byte '%lf %lf',0
Outfmt byte '%g',0
.code
start:
invoke scanf,addr Infmt,addr x,addr y
fld s
.while eax==2
fld x
fmul y
fstp z
fadd z
invoke scanf,addr Infmt,addr x,addr y
.endw
fstp s
invoke printf,addr Outfmt,s
invoke ExitProcess,0
end start
;*】*/
3、键盘输入一串字符(最多80个字符),输出其中的数字。
运行后若输入:ab4du5jkf8
则结果输出:458
请在;*【*/和;*】*/之间编写程序。
/***源程序asm***/
;*【*/
.386
.model flat, stdcall
include kernel32.inc
includelib kernel32.lib
includelib msvcrt.lib ;引用C库文件
printf PROTO C:ptr sbyte,:vararg ;C语言printf函数原型声明
scanf PROTO C:ptr sbyte,:vararg ;C语言scanf函数原型声明
option casemap :none
.data
s byte 80 dup(0)
Infmt byte '%s',0
Outfmt byte '%c',0
.code
start:
invoke scanf,addr Infmt,addr s
lea esi,s
.while byte ptr[esi]!=0
.if byte ptr[esi]>='0' && byte ptr[esi]<='9'
mov al,byte ptr[esi]
invoke printf,addr Outfmt,al
.endif
inc esi
.endw
invoke ExitProcess,0
end start
;*】*/
题型六:c嵌入汇编
1、键盘输入a和b两串字符,编程实现将a串和b串连接的结果存入字符数组c[50]并输出。
如:
运行后输入:ABCD abcd
则结果输出:ABCDabcd
运行后输入:AB a
则结果输出:ABa
请在/*【*/和/*】*/之间编写程序。
注意:不要删除或增加/*【*/和/*】*/。
#include "stdio.h"
#include "string.h"
void main()
{
char a[50]="ABCD",b[50]="abcd",c[50]={0};
int n,m;
scanf("%s %s",a,b);
n=strlen(a);m=strlen(b);
__asm
{
/*【*/
cld
lea esi,a
lea edi,c
mov ecx,n
rep movsb
lea esi,b
lea edi,c
add edi,n
mov ecx,m
rep movsb
/*】*/
}
printf("%s",c);
}
2、将字符数组a[63]中的数字删除(相当于把字母移到起始位置)。
注意:字符串结束标志也移。
如:
运行后输入:null(不输入)
则结果输出:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
请在/*【*/和/*】*/之间编写程序。
注意:不要删除或增加/*【*/和/*】*/。
/***源程序***/
#include "stdio.h"
void main()
{
char a[63]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
__asm
{
/*【*/
cld
lea esi,a+10
lea edi,a
mov ecx,53
rep movsb
/*】*/
}
printf("%s",a);
}
题型七:子程序
1、编一串拷贝子程序,实现C语言char* strcpy(char *Dst,char *Src)函数,然后主程序调用strcpy(s1,s2)实现s2串拷贝到s1串。
运行后输入:
ABCD
则结果输出:
ABCD
请在;*【*/和;*】*/之间编写程序。
/***源程序asm***/
.386 ;选择的处理器
.model flat, stdcall ;存储模型,Win32程序只能用平展(flat)模型
option casemap:none ;指明标识符大小写敏感
include kernel32.inc ;要引用的头文件
includelib kernel32.lib ;要引用的库文件
includelib msvcrt.lib ;引用C库文件
scanf PROTO C:DWORD,:vararg ;C语言scanf函数原型声明
printf PROTO C:DWORD,:vararg ;C语言printf函数原型声明
.data ;⑤数据段
fmt BYTE '%s',0 ;定义变量
s1 BYTE 80 Dup(0)
s2 BYTE 80 Dup(0)
.code ;⑥代码段
;*【*/
strcpy proc,Str1:dword,Str2:dword
mov esi,Str1
mov edi,Str2
.while byte ptr[esi]!=0
inc esi
.endw
.while byte ptr[edi]!=0
mov al,byte ptr[edi]
mov byte ptr[esi],al
inc esi
inc edi
.endw
ret
strcpy endp
;*】*/
start: ;定义标号start
invoke scanf,ADDR fmt,ADDR s2 ;输入s2的值
invoke strcpy,ADDR s1,ADDR s2 ;求s2串拷贝到s1串
invoke printf,ADDR fmt,ADDR s1 ;输出
invoke ExitProcess,0 ;退出进程,返回值为0
end start ;指明程序入口点start
2、编一函数MaxN(int a[],int n)用于求n个元素的数组a中的最大元素。
运行后输入:
1 3 4 5 2
则结果输出:
最大值为5
运行后输入:
1 3 6 4 5 2
则结果输出:
最大值为6
请在;*【*/和;*】*/之间编写程序。
/***源程序asm***/
.386 ;选择的处理器
.model flat, stdcall ;存储模型,Win32程序只能用平展(flat)模型
option casemap:none ;指明标识符大小写敏感
include kernel32.inc ;要引用的头文件
includelib kernel32.lib ;要引用的库文件
includelib msvcrt.lib ;引用C库文件
scanf PROTO C:DWORD,:vararg ;C语言scanf函数原型声明
printf PROTO C:DWORD,:vararg ;C语言printf函数原型声明
.data ;⑤数据段
Infmt BYTE '%d',0
Outfmt BYTE '最大值为%d',0
a DWORD 80 Dup(0) ;定义数组a
.code ;⑥代码段
;*【*/
MaxN proc,s:dword,i:dword
mov esi,0
mov ebx,s
mov eax,[ebx+esi*4]
.while esi<i
.if [ebx+esi*4]>eax
mov al,[ebx+esi*4]
.endif
inc esi
.endw
ret
MaxN endp
;*】*/
start: ;定义标号start
mov ESI,0
invoke scanf,ADDR Infmt,ADDR a[ESI*4];输入a[i]的值
.while EAX==1
INC ESI
invoke scanf,ADDR Infmt,ADDR a[ESI*4];
.endw
invoke MaxN,ADDR a,ESI ;求a数组和通过EAX返回
invoke printf,ADDR Outfmt,EAX;输出结果
invoke ExitProcess,0 ;退出进程,返回值为0
end start ;指明程序入口点start