data segment ; 定义数据段
infon db 0dh,0ah,'Please input a year: $'
Y db 0dh,0ah,'This is a leap year! $'
N db 0dh,0ah,'This is not a leap year! $'
w dw 0 ; the value of user input
buf db 8 ; the max capicity of buffer
db ? ; 预留一个字节的空间,值未知 record the length of user input
db 8 dup(?) ; 预留八个字节的空间,值未知 record the string of user input
data ends
stack segment stack
db 200 dup(0)
stack ends
code segment
assume ds:data,ss:stack,cs:code
start:mov ax,data
mov ds,ax
lea dx,infon
mov ah,9
int 21h ; 在屏幕上显示提示信息
lea dx,buf
mov ah,10
int 21h ; 从键盘输入年份字符串
mov cl, [buf+1]
lea di,buf+2 ; the first byte of input year string
call datacate
call ifyears
jc a1
; no
lea dx,n
mov ah,9
int 21h
jmp exit
; yes
a1: lea dx,y
mov ah,9
int 21h
; exit
exit: mov ah,4ch
int 21h
datacate proc near ; put the value user input to w word byte unit
push cx; ; mov cl, [buf+1]
dec cx ; 'the length of input year' - 1
lea si,buf+2
tt1: inc si
loop tt1 ; the last byte of input year
;lea si,cx[di]
pop cx
mov dh,30h
mov bl,10
mov ax,1
l1: push ax ; no value change in loop, this is not necessary ? no, the mul instruction will change ax
sub byte ptr [si],dh ; get the value of input
mul byte ptr [si]
add w,ax ; add value to w word byte
pop ax ; return ax's value to last ax's last value
mul bl ; turn ax's value to 10 * ax's value
dec si
loop l1
ret
datacate endp
ifyears proc near
push bx
push cx
push dx
mov ax,w ; get the year which is user input
mov cx,ax
mov dx,0
mov bx,4
div bx ;
cmp dx,0 ; dx's value is the remainder of 'divide' result
jnz lab1 ; jump if not equal
;------------------ the year could be completely divided by 4
mov ax,cx
mov bx,100
div bx
cmp dx,0
jnz lab2
;----------------- the year could be completely divided by 100
mov ax,cx
mov bx,400
div bx
cmp dx,0
jz lab2
;----------------- the year couldn't be completely divided by 400
jmp lab1
lab1: clc ; clear carry flag
jmp lab3
lab2: stc ; set carry flag
lab3: pop dx
pop cx
pop bx
ret
ifyears endp
code ends
end start
; 这是我的第一个较为完整的汇编程序,做了两个多小时..... --2014.07.22
db 指令相关, 来源于网上
; 1. ------------------------- db 指令
; DB 是Define Byte的简写,就是定义一个字节的意思。
; “假设OP1,OP2是已经用DB定义的变量”也就是说定义两个字节变量,变量名为OP1和OP2。
; dataseg segment
; aa db ?
; bb db ?
; cc db ?
; dataseg ends
;
; 上面的DB又是什么意思?问号呢?
; 定义的数据段,段名为dataseg,在该代码段中有三个字节变量,名称分别是aa,bb,cc,而且每个变量都没有赋值。也就是空的。; ?的意思就是说定义的变量所在的内存单元没有赋值,预留一个内存单元的空间。
; 2. ------------------------- db 指令
; DB定义的,是一个字节类型的指针,完全没有容量的概念, 不存在容量的限制,没有存不下的问题。
; 数据存储从指针所指向的地址开始往下分配,需要填多少数据都可以。(当然还有一个段的大小不能超过64KB的限制)
; 你的困惑,是你强行将高级语言中一个变量只能存一个数据、是一个数据容器的概念直接拿来套用造成的。这样的概念对于汇编语言来说是错误的。
; 如果你这样定义:
; XY DB 05H, 43H, 21H, 32H
; 那么,内存中数据就这么分布
; 地址 数据
; XY+0 05
; XY+1 43
; XY+2 21
; XY+3 32
; 如果你改成这样定义:
; XZ DW 4305H, 3221H
; 那么,内存中数据这么分布:
; XZ+0 05
; XZ+1 43
; XZ+2 21
; XZ+3 32
; 可以看出,这两种定义方式,数据在内存的分布是一模一样的。
; 区别仅仅是变量名的数据类型的属性不同。
; 如果你程序中这样用数据:
; MOV AL, XY
; MOV AH, XY+1
; 结果AX的内容变成4305H
; 与用指令 MOV AX, XZ 的结果也是一模一样。
; ===========
; 对你问题的补充的回复:
; ===========
; 在汇编语言中,并不需要为每个数据存储单元定义一个名字。
; 数据是可以直接按地址访问的。
; 实际上,经汇编程序翻译以后,和变量名就变成了直接按地址访问。
; 机器指令也只能按地址访问。
; 按地址访问数据时,需要明确数据类型。
; 定义一个名字,用名字代表具体的地址值(同时也隐含着数据类型), 是为了让汇编程序在汇编时,将指令中的变量名替换为地址,减少编程者的人工工作量,便于编写程序。
; 3. ------------------------- proc 指令
; PROC在汇编中是过程定义伪指令的意思
; 关于汇编中proc near与proc far的用法
; 如果你的子程序和主程序在同一个代码段,则使用near,调用发生后,主程序堆栈中只压入ip值;
; 如果你的子程序和主程序不在一个代码段,则使用far,调用发生后,主程序堆栈中将压入cs、ip值;
----------------------------------------------------------------------------------------------------------
# add at 2015.12.14
效果截图 :