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值;