一开始的代码:
void print(){
printf("hello hairi");
}
lib1的代码
include Lib1.lib
data segment ;定义数据段
infon db 0dh,0ah,'Please input a year: $' ;infon ,双字节,回车换行,内容
Y db 0dh,0ah,'This is a leap year! $' ;y ,双字节,回车换行,内容
N db 0dh,0ah,'This is not a leap year! $' ;n ,双字节,回车换行,内容($是结束符)
w dw 0 ;w为双字类型
buf db 8 ;开辟8个双字节类型的缓冲区,未赋值
db ?
db 8 dup(?)
data ends
stack segment stack
db 200 dup(0) ;开辟200个双字节类型的存储空间。(保护现场用到)
stack ends
code segment
assume ds:data,ss:stack,cs:code
start:mov ax,data ;寄存器间的数据交换,把data给了数据段
mov ds,ax
invoke print,NULL ;添加hello hairi
lea dx,infon ;在屏幕上显示提示信息
mov ah,9
int 21h
lea dx,buf ;从键盘输入年份字符串
mov ah,10
int 21h
mov cl, [buf+1] ;把buf+1地址指向的内容给cl,buf长度
lea di,buf+2 ;把buf+2的地址给di,buf偏移地址
call datacate ;调用函数datacate,传递参数
call ifyears ;调用函数ifyears,由参数判断是否为闰年
jc a1 ;若产生进位就跳到a1处
lea dx,n ;dx加载n的地址'This is not a leap year!'
mov ah,9 ;显示dx内的内容
int 21h
jmp exit ;跳到exit
a1: lea dx,y ;dx加载y的地址'This is a leap year!'
mov ah,9
int 21h
exit: mov ah,4ch ;结束本程序,返回 DOS 操作系统
int 21h
;实现将字符串的闰年转换为数字存储在ax中
datacate proc near; ;段内调用,子函数1
push cx; ;保护现场
dec cx
lea si,buf+2 ;把buf+2的地址给si
tt1: inc si ;移动到字符串指定位置
loop tt1 ;循环函数是个递增函数, loop指令的格式是:loop标号,cpu执行loop指令的时候,要进行两步操作
;1:(cx)=(cx)-1
;2:判断cx中的值,不为零则转至标号处执行,如果为零,则向下执行
;lea si,cx[di]
pop cx ;恢复现场
mov dh,30h
mov bl,10 ;乘数设置为10
mov ax,1
l1: push ax ;保护现场
sub byte ptr [si],dh ;没有寄存器参与的内存单元访问指令(DMA),si-dh保存在si中
mul byte ptr [si] ;没有寄存器参与的内存单元访问指令(DMA),ax*si,结果放在eax中,这里的寄存器si是16位,被乘数在ax中也是16位。
;MUL r/m(寄存器或者内存) ;mul是字内乘法,把si对应的地址内一个字的长度赋给
;如果参数是 r8/m8, 将把 AL 做乘数, 结果放在 AX
;如果参数是 r16/m16, 将把 AX 做乘数, 结果放在 EAX
;如果参数是 r32/m32, 将把 EAX 做乘数, 结果放在 EDX:EAX
add w,ax ;w+ax,结果存入w,存入的是数字
pop ax ;恢复现场
mul bl ;bl*al,结果存放在ax中
dec si ;si中的内容减一
loop l1 ;l1循环,cx判断次数
ret
datacate endp
;实现ax中年份的判断
ifyears proc near ;段内调用,子函数2
push bx ;保护现场(保护谁,就用到谁)
push cx
push dx
mov ax,w ;把w值赋给cx,w值为
mov cx,ax ;把ax值赋给cx
mov dx,0
mov bx,4 ;ax/4
div bx ;ax/bx,结果在ax中,余数在dx中
;如果除数是8位,那么除法的结果AL保存商,AH保存余数,
;如果除数是16位,那么除法的结果 AX保存商,DX保存余数。
cmp dx,0 ;比较余数和0,结果存入cf标志位(进位标志位)
jnz lab1 ;如果非0,跳转到lab1处
mov ax,cx
mov bx,100 ;ax/100
div bx
cmp dx,0 ;比较余数和0,结果存入cf标志位(进位标志位)
jnz lab2 ;如果非0,跳到lab2
mov ax,cx
mov bx,400 ;ax/400
div bx
cmp dx,0 ;比较余数和0,结果存入cf标志位(进位标志位)
jz lab2 ;cf=0跳到lab2
lab1: clc ;清除cf标志位,设置cf=0
jmp lab3 ;跳到lab3
lab2: stc ;cf置1
lab3: pop dx ;恢复现场
pop cx
pop bx
ret
ifyears endp
code ends
end start
报错:
error A2105:错误是指invoke语句不识别
可能原因:路径错误,缺少函数声明
注:Includelib的默认搜索路径是c盘(mount 指定的c盘)
注:Masm.exe和link.exe不需要依赖include和lib文件夹,移除两个文件夹的内容后依旧可以编译链接
修改代码如下:
includelib Lib1.lib
extrn print:far
data segment ;定义数据段
infon db 0dh,0ah,'Please input a year: $' ;infon ,双字节,回车换行,内容
Y db 0dh,0ah,'This is a leap year! $' ;y ,双字节,回车换行,内容
N db 0dh,0ah,'This is not a leap year! $' ;n ,双字节,回车换行,内容($是结束符)
w dw 0 ;w为双字类型
buf db 8 ;开辟8个双字节类型的缓冲区,未赋值
db ?
db 8 dup(?)
data ends
stack segment stack
db 200 dup(0) ;开辟200个双字节类型的存储空间。(保护现场用到)
stack ends
code segment
assume ds:data,ss:stack,cs:code
start:mov ax,data ;寄存器间的数据交换,把data给了数据段
mov ds,ax
call print ;添加hello hairi
lea dx,infon ;在屏幕上显示提示信息
mov ah,9
int 21h
lea dx,buf ;从键盘输入年份字符串
mov ah,10
int 21h
mov cl, [buf+1] ;把buf+1地址指向的内容给cl,buf长度
lea di,buf+2 ;把buf+2的地址给di,buf偏移地址
call datacate ;调用函数datacate,传递参数
call ifyears ;调用函数ifyears,由参数判断是否为闰年
jc a1 ;若产生进位就跳到a1处
lea dx,n ;dx加载n的地址'This is not a leap year!'
mov ah,9 ;显示dx内的内容
int 21h
jmp exit ;跳到exit
a1: lea dx,y ;dx加载y的地址'This is a leap year!'
mov ah,9
int 21h
exit: mov ah,4ch ;结束本程序,返回 DOS 操作系统
int 21h
;实现将字符串的闰年转换为数字存储在ax中
datacate proc near; ;段内调用,子函数1
push cx; ;保护现场
dec cx
lea si,buf+2 ;把buf+2的地址给si
tt1: inc si ;移动到字符串指定位置
loop tt1 ;循环函数是个递增函数, loop指令的格式是:loop标号,cpu执行loop指令的时候,要进行两步操作
;1:(cx)=(cx)-1
;2:判断cx中的值,不为零则转至标号处执行,如果为零,则向下执行
;lea si,cx[di]
pop cx ;恢复现场
mov dh,30h
mov bl,10 ;乘数设置为10
mov ax,1
l1: push ax ;保护现场
sub byte ptr [si],dh ;没有寄存器参与的内存单元访问指令(DMA),si-dh保存在si中
mul byte ptr [si] ;没有寄存器参与的内存单元访问指令(DMA),ax*si,结果放在eax中,这里的寄存器si是16位,被乘数在ax中也是16位。
;MUL r/m(寄存器或者内存) ;mul是字内乘法,把si对应的地址内一个字的长度赋给
;如果参数是 r8/m8, 将把 AL 做乘数, 结果放在 AX
;如果参数是 r16/m16, 将把 AX 做乘数, 结果放在 EAX
;如果参数是 r32/m32, 将把 EAX 做乘数, 结果放在 EDX:EAX
add w,ax ;w+ax,结果存入w,存入的是数字
pop ax ;恢复现场
mul bl ;bl*al,结果存放在ax中
dec si ;si中的内容减一
loop l1 ;l1循环,cx判断次数
ret
datacate endp
;实现ax中年份的判断
ifyears proc near ;段内调用,子函数2
push bx ;保护现场(保护谁,就用到谁)
push cx
push dx
mov ax,w ;把w值赋给cx,w值为
mov cx,ax ;把ax值赋给cx
mov dx,0
mov bx,4 ;ax/4
div bx ;ax/bx,结果在ax中,余数在dx中
;如果除数是8位,那么除法的结果AL保存商,AH保存余数,
;如果除数是16位,那么除法的结果 AX保存商,DX保存余数。
cmp dx,0 ;比较余数和0,结果存入cf标志位(进位标志位)
jnz lab1 ;如果非0,跳转到lab1处
mov ax,cx
mov bx,100 ;ax/100
div bx
cmp dx,0 ;比较余数和0,结果存入cf标志位(进位标志位)
jnz lab2 ;如果非0,跳到lab2
mov ax,cx
mov bx,400 ;ax/400
div bx
cmp dx,0 ;比较余数和0,结果存入cf标志位(进位标志位)
jz lab2 ;cf=0跳到lab2
lab1: clc ;清除cf标志位,设置cf=0
jmp lab3 ;跳到lab3
lab2: stc ;cf置1
lab3: pop dx ;恢复现场
pop cx
pop bx
ret
ifyears endp
code ends
end start
编译成功,链接出现问题
可能原因:lib库位置出错,16位编译器无法编译32位的lib库
改用Masm32 edit
使用Masm32 edit,依然报错:
原因:Masm611的语法和masm32的语法不同。
使用masm生成的obj进行link,依然报错:
原因:使用16位生成的obj去进行32位的link操作不合理