汇编语言程序设计实例,汇编语言程序设计
汇编语言程序设计实例,汇编语言程序设计详细介绍
本文目录一览: 汇编语言程序设计实例
第一题:mov cl,0
mov ch,17
next:dec ch
je exit
mov bx,0
shl ax,1
rol bx,1
cmp bx,0
jz next
inc cl
jmp next
exit:mov ah,4ch
int 21h
第二题:
mov cx,10
mov si,offset buffer
next:mov bx,word ptr[si]
inc bx
mov word ptr[si],bx
inc si
inc si
loop exit
jmp next
exit: mov ah,4ch
int 21h
汇编语言程序设计
由于我也是刚学的只能用16进制了,还有没啥注释 这没办法啊 !我还没睡中午就上课了,就这些了:
data segment
k1 db 10 dup(?)
k2 db 10 dup(?)
out1 db 'input data k1',13,10,'$'
out2 db 'input data k2',13,10,'$'
data ends
code segment
main proc far
assume cs:code,ds:data
start:
push ds
mov ax,0
push ax
mov ax,data
mov ds,ax
mov es,ax
;input k1
lea dx,out1
mov ah,09
int 21h
mov ah,0ah
lea dx,k1
int 21h
cmp k1,0
je exit
;input k2
lea dx,out2
mov ah,09
int 21h
mov ah,0ah
lea dx,k2
int 21h
cmp k2,0
je exit
;add
mov bx,k1
add bx,k2
;2 to 16
mov ch,4
rotate:
mov cl,4
rol bx,cl
mov al,bl
and al,0fh
add al,30h
cmp al,3ah
jl printit
add al,7h
printit:
mov dl,al
mov ah,2
int 21h
dec ch
jnz rotate
ret
exit:
ret
main endp
code ends
end main
name "calc2"
; command prompt based simple calculator (+,-,*,/) for 8086.
; example of calculation:
; input 1 <- number: 10
; input 2 <- operator: -
; input 3 <- number: 5
; -------------------
; 10 - 5 = 5
; output -> number: 5
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; this maro is copied from emu8086.inc ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; this macro prints a char in AL and advances
; the current cursor position:
PUTC MACRO char
PUSH AX
MOV AL, char
MOV AH, 0Eh
INT 10h
POP AX
ENDM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 100h
jmp start
; define variables:
msg0 db "note: calculator works with integer values only.",0Dh,0Ah
db "to learn how to output the result of a float division see float.asm in examples",0Dh,0Ah,'$'
msg1 db 0Dh,0Ah, 0Dh,0Ah, 'enter first number: $'
msg2 db "enter the operator: + - * / : $"
msg3 db "enter second number: $"
msg4 db 0dh,0ah , 'the approximate result of my calculations is : $'
msg5 db 0dh,0ah ,'thank you for using the calculator! press any key... ', 0Dh,0Ah, '$'
err1 db "wrong operator!", 0Dh,0Ah , '$'
smth db " and something.... $"
; operator can be: '+','-','*','/' or 'q' to exit in the middle.
opr db '?'
; first and second number:
num1 dw ?
num2 dw ?
start:
mov dx, offset msg0
mov ah, 9
int 21h
lea dx, msg1
mov ah, 09h ; output string at ds:dx
int 21h
; get the multi-digit signed number
; from the keyboard, and store
; the result in cx register:
call scan_num
; store first number:
mov num1, cx
; new line:
putc 0Dh
putc 0Ah
lea dx, msg2
mov ah, 09h ; output string at ds:dx
int 21h
; get operator:
mov ah, 1 ; single char input to AL.
int 21h
mov opr, al
; new line:
putc 0Dh
putc 0Ah
cmp opr, 'q' ; q - exit in the middle.
je exit
cmp opr, '*'
jb wrong_opr
cmp opr, '/'
ja wrong_opr
; output of a string at ds:dx
lea dx, msg3
mov ah, 09h
int 21h
; get the multi-digit signed number
; from the keyboard, and store
; the result in cx register:
call scan_num
; store second number:
mov num2, cx
lea dx, msg4
mov ah, 09h ; output string at ds:dx
int 21h
; calculate:
cmp opr, '+'
je do_plus
cmp opr, '-'
je do_minus
cmp opr, '*'
je do_mult
cmp opr, '/'
je do_div
; none of the above....
wrong_opr:
lea dx, err1
mov ah, 09h ; output string at ds:dx
int 21h
exit:
; output of a string at ds:dx
lea dx, msg5
mov ah, 09h
int 21h
; wait for any key...
mov ah, 0
int 16h
ret ; return back to os.
do_plus:
mov ax, num1
add ax, num2
call print_num ; print ax value.
jmp exit
do_minus:
mov ax, num1
sub ax, num2
call print_num ; print ax value.
jmp exit
do_mult:
mov ax, num1
imul num2 ; (dx ax) = ax * num2.
call print_num ; print ax value.
; dx is ignored (calc works with tiny numbers only).
jmp exit
do_div:
; dx is ignored (calc works with tiny integer numbers only).
mov dx, 0
mov ax, num1
idiv num2 ; ax = (dx ax) / num2.
cmp dx, 0
jnz approx
call print_num ; print ax value.
jmp exit
approx:
call print_num ; print ax value.
lea dx, smth
mov ah, 09h ; output string at ds:dx
int 21h
jmp exit
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; these functions are copied from emu8086.inc ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; gets the multi-digit SIGNED number from the keyboard,
; and stores the result in CX register:
SCAN_NUM PROC NEAR
PUSH DX
PUSH AX
PUSH SI
MOV CX, 0
; reset flag:
MOV CS:make_minus, 0
next_digit:
; get char from keyboard
; into AL:
MOV AH, 00h
INT 16h
; and print it:
MOV AH, 0Eh
INT 10h
; check for MINUS:
CMP AL, '-'
JE set_minus
; check for ENTER key:
CMP AL, 0Dh ; carriage return?
JNE not_cr
JMP stop_input
not_cr:
CMP AL, 8 ; 'BACKSPACE' pressed?
JNE backspace_checked
MOV DX, 0 ; remove last digit by
MOV AX, CX ; division:
DIV CS:ten ; AX = DX:AX / 10 (DX-rem).
MOV CX, AX
PUTC ' ' ; clear position.
PUTC 8 ; backspace again.
JMP next_digit
backspace_checked:
; allow only digits:
CMP AL, '0'
JAE ok_AE_0
JMP remove_not_digit
ok_AE_0:
CMP AL, '9'
JBE ok_digit
remove_not_digit:
PUTC 8 ; backspace.
PUTC ' ' ; clear last entered not digit.
PUTC 8 ; backspace again.
JMP next_digit ; wait for next input.
ok_digit:
; multiply CX by 10 (first time the result is zero)
PUSH AX
MOV AX, CX
MUL CS:ten ; DX:AX = AX*10
MOV CX, AX
POP AX
; check if the number is too big
; (result should be 16 bits)
CMP DX, 0
JNE too_big
; convert from ASCII code:
SUB AL, 30h
; add AL to CX:
MOV AH, 0
MOV DX, CX ; backup, in case the result will be too big.
ADD CX, AX
JC too_big2 ; jump if the number is too big.
JMP next_digit
set_minus:
MOV CS:make_minus, 1
JMP next_digit
too_big2:
MOV CX, DX ; restore the backuped value before add.
MOV DX, 0 ; DX was zero before backup!
too_big:
MOV AX, CX
DIV CS:ten ; reverse last DX:AX = AX*10, make AX = DX:AX / 10
MOV CX, AX
PUTC 8 ; backspace.
PUTC ' ' ; clear last entered digit.
PUTC 8 ; backspace again.
JMP next_digit ; wait for Enter/Backspace.
stop_input:
; check flag:
CMP CS:make_minus, 0
JE not_minus
NEG CX
not_minus:
POP SI
POP AX
POP DX
RET
make_minus DB ? ; used as a flag.
SCAN_NUM ENDP
; this procedure prints number in AX,
; used with PRINT_NUM_UNS to print signed numbers:
PRINT_NUM PROC NEAR
PUSH DX
PUSH AX
CMP AX, 0
JNZ not_zero
PUTC '0'
JMP printed
not_zero:
; the check SIGN of AX,
; make absolute if it's negative:
CMP AX, 0
JNS positive
NEG AX
PUTC '-'
positive:
CALL PRINT_NUM_UNS
printed:
POP AX
POP DX
RET
PRINT_NUM ENDP
; this procedure prints out an unsigned
; number in AX (not just a single digit)
; allowed values are from 0 to 65535 (FFFF)
PRINT_NUM_UNS PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
; flag to prevent printing zeros before number:
MOV CX, 1
; (result of "/ 10000" is always less or equal to 9).
MOV BX, 10000 ; 2710h - divider.
; AX is zero?
CMP AX, 0
JZ print_zero
begin_print:
; check divider (if zero go to end_print):
CMP BX,0
JZ end_print
; avoid printing zeros before number:
CMP CX, 0
JE calc
; if AX
<bx then result of div will be zero:
CMP AX, BX
JB skip
calc:
MOV CX, 0 ; set flag.
MOV DX, 0
DIV BX ; AX = DX:AX / BX (DX=remainder).
; print last digit
; AH is always ZERO, so it's ignored
ADD AL, 30h ; convert to ASCII code.
PUTC AL
MOV AX, DX ; get remainder from last div.
skip:
; calculate BX=BX/10
PUSH AX
MOV DX, 0
MOV AX, BX
DIV CS:ten ; AX = DX:AX / 10 (DX=remainder).
MOV BX, AX
POP AX
JMP begin_print
print_zero:
PUTC '0'
end_print:
POP DX
POP CX
POP BX
POP AX
RET
PRINT_NUM_UNS ENDP
ten DW 10 ; used as multiplier/divider by SCAN_NUM & PRINT_NUM_UNS.
GET_STRING PROC NEAR
PUSH AX
PUSH CX
PUSH DI
PUSH DX
MOV CX, 0 ; char counter.
CMP DX, 1 ; buffer too small?
JBE empty_buffer ;
DEC DX ; reserve space for last zero.
;============================
; Eternal loop to get
; and processes key presses:
wait_for_key:
MOV AH, 0 ; get pressed key.
INT 16h
CMP AL, 0Dh ; 'RETURN' pressed?
JZ exit_GET_STRING
CMP AL, 8 ; 'BACKSPACE' pressed?
JNE add_to_buffer
JCXZ wait_for_key ; nothing to remove!
DEC CX
DEC DI
PUTC 8 ; backspace.
PUTC ' ' ; clear position.
PUTC 8 ; backspace again.
JMP wait_for_key
add_to_buffer:
CMP CX, DX ; buffer is full?
JAE wait_for_key ; if so wait for 'BACKSPACE' or 'RETURN'...
MOV [DI], AL
INC DI
INC CX
; print the key:
MOV AH, 0Eh
INT 10h
JMP wait_for_key
;============================
exit_GET_STRING:
; terminate by null:
MOV [DI], 0
empty_buffer:
POP DX
POP DI
POP CX
POP AX
RET
GET_STRING ENDP
求助:一道简单的汇编语言程序设计
assume cs:code,ds:data,ss:stack
data segment
db 85,81,72,57,36,92,100,63,95
msg db "<60,60-69,70-79,80-89,90-99,=100 :",0dh,0ah,"$"
space db " $" ;成绩数之间的显示间隔
data ends
stack segment
dw 9 dup (0) ;主要用来保存各个区间的成绩数
stack ends
code segment
start:
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,18
mov al,110
mov cx,6 ;6个区间
;以取值区间为对象来循环,每个成绩至少比较了6次(与区间上下限相比):
compare:
mov bx,8 ;从最后一个成绩开始判断
mov di,0 ;区间成绩数初始为0
push cx ;call前保存外部循环次数
mov cx,9 ;9个成绩
call calc
pop cx ;call后恢复外部循环次数
push di
sub al,10
loop compare
;显示结果:{
mov dx,offset msg
mov ah,9
int 21h
mov cx,6
printNum:
;输出成绩数
pop ax
add ax,30h ;数字转换为字符
mov dl,al
mov ah,2
int 21h
;输出成绩数之间的间隔:
mov dx,offset space
mov ah,9
int 21h
loop printNum
;}
mov ah,0
int 16h
mov ax,4c00h
int 21h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;本子程序确定落在某个成绩区间里的成绩数
calc:
push ax
cmp byte ptr [bx],al
jnb nextArea
cmp al,60
je addNum
sub al,10
cmp byte ptr [bx],al
jb nextArea
addNum:
inc di
nextArea:
pop ax
dec bx
loop calc
ret
code ends
end start
我考!才100分!花了我一点时间!绝对是正确的!
DATA SEGMENT
HAN DB 42,62,68,70,79,82,85,90,95
MEM DB 6 dup(30h),'$' ;分别用于存放各分数段成绩的个数
DATA ENDS
CODE SEGMENT
ASSUME DS:DATA,CS:CODE
START: MOV AX,DATA
MOV DS,AX
MOV CX,9
mov si,0
begin:
.if han[si]<60
add mem[0],1
.elseif han[si]>=60 && han[si]<=69
add mem[1],1
.elseif han[si]>=70 && han[si]<=79
add mem[2],1
.elseif han[si]>=80 && han[si]<=89
add mem[3],1
.elseif han[si]>=90 && han[si]<=99
add mem[4],1
.else
add mem[5],1
.endif
inc si
loop begin
mov dx,offset mem ;显示统计结果122220
mov ah,9
int 21h
MOV AX,4C00H
INT 21H
CODE ENDS
END START
dataseg segment
grade dw 76,69,84,90,73,88,99,63,100
s5 db 0
s6 db 0
s7 db 0
s8 db 0
s9 db 0
s10 db 0
dataseg ends
cseg segment
main proc far
assume cs:cseg,ds:dataseg
start:
push ds
sub ax,ax
push ax
mov ax,dataseg
mov ds,ax
mov cx,9
call count
call disp
mov ah,1
int 21h
ret
main endp
count proc near
mov si,0
next:mov ax,grade[si]
mov bl,10
div bl
mov bl,al
mov bh,0
sub bx,5
cmp bx,0
jae next1
mov bx,0
next1:
inc s5[bx]
add si,2
loop next
ret
count endp
disp proc near
lea si,s5
mov cx,6
loop1:
mov dl,[si]
add dl,30h
mov ah,2
int 21h
inc si
loop loop1
ret
disp endp
cseg ends
end start
前面不带点的if是8086中宏汇编的条件汇编
前面带点的if是win32汇编中的伪指令
路过,看了看---两个字```不会!
因为我也正在学,不好意思哦!
8086汇编语言,使用masm5汇编器编译通过
data segment
score db 30,40,50,60,70,80,90,67,70 ;9个学生的分数
num_under60 db 0 ;60以下的人数
num_60to69 db 0 ;60到69的人数
num_70to79 db 0 ;70到79的人数
num_80to89 db 0 ;80到89的人数
num_90to99 db 0 ;90到99的人数
num_100 db 0 ;100的人数
data ends
code segment
assume cs:code,ds:data
start:
mov ax,data
mov ds,ax
xor ax,ax
mov cx,9 ;循环9次
lea bx,score
compare:
cmp byte ptr [bx],60 ;与60比较
jl under60
jmp is60to69
is60to69:
cmp byte ptr [bx],70 ;与70比较
jl _60to69
jmp is70to79
is70to79:
cmp byte ptr [bx],80 ;与80比较
jl _70to79
jmp is80to89
is80to89:
cmp byte ptr [bx],90 ;与90比较
jl _80to89
jmp is90to99
is90to99:
cmp byte ptr [bx],100 ;与100比较
jl _90to99
jz equal100
under60: ;如果低于60
add num_under60,1
jmp con
_60to69: ;如果在60到69之间
add num_60to69,1
jmp con
_70to79: ;如果在70到79之间
add num_70to79,1
jmp con
_80to89: ;如果在80到89之间
add num_80to89,1
jmp con
_90to99: ;如果在90到99之间
add num_90to99,1
jmp con
equal100: ;如果等于100
add num_100,1
con:
lea bx,[bx+1]
loop compare
last: ;输出
mov dl,num_under60 ;输出60以下的人数
add dl,30h
mov ah,2
int 21h
mov dl,num_60to69 ;输出60到69的人数
add dl,30h
mov ah,2
int 21h
mov dl,num_70to79 ;输出70到79的人数
add dl,30h
mov ah,2
int 21h
mov dl,num_80to89 ;输出80到89的人数
add dl,30h
mov ah,2
int 21h
mov dl,num_90to99 ;输出90到99的人数
add dl,30h
mov ah,2
int 21h
mov dl,num_100 ;输出100的人数
add dl,30h
mov ah,2
int 21h
mov ah,4ch ;返回DOS
int 21h
code ends
end start
汇编语言程序设计
比较
; 本程序通过编译,运行正确
Code Segment
Assume CS:Code,DS:Code
; -----------------------------------------
; 功能:显示指定地址(Str_Addr)的字符串
; 入口:
; Str_Addr=字符串地址(要求在数据段)
; 用法: Output Str_Addr
; 用法举例:Output PromptStr
Output MACRO Str_Addr
lea dx,Str_Addr
mov ah,9
int 21h
EndM
; -----------------------------------------
; 功能:输出回车换行
Output_CTLF proc Near
push ax
push dx
mov ah,02h
mov dl,0dh
int 21h
mov dl,0ah
int 21h
pop dx
pop ax
ret
Output_CTLF endp
; -----------------------------------------
; 功能:把AX中的二进制无符号数转换成显式的十进制ASCII码,并送显示屏显示
; 入口:AX=二进制数
; 出口:在当前光标位置显示转换后的ASCII码数字
Dec_ASCII Proc Near
push dx
push bx
push di
mov bx,10
lea di,@@Temp_Save[6]
mov byte ptr [di],'$'
dec di
cld
@@Divide: xor dx,dx
div bx
or dl,30h
mov [di],dl
dec di
test ax,0ffffh
jnz @@Divide
inc di
push di
pop dx
mov ah,9
int 21h
pop di
pop bx
pop dx
ret
@@Temp_Save db 7 dup(?)
Dec_ASCII EndP
; -----------------------------------------
; 功能:在N个字节数组中查找字符CHAR,并记录该字符出现的次数。
; 入口参数:
; si=一个N字节数的字符串TABLE首地址
; cx=字符串长度,N
; ah=要查找的字符
; 出口参数:bl=该字符出现的次数
Find_Chr Proc Near
@@Find_Chr: lodsb
cmp al,ah ;是指定的字符?
jnz $+4 ;不是
inc bl ;是,计数
loop Find_Chr ;判断下一个字符
ret
Find_Chr EndP
; -----------------------------------------
Prompt_Str db 'Please input a string: $' ;输入字符串提示信息
No_String db 'The string is null.$' ;空字符串提示信息
Prompt_Chr db 'Please input a charactor: $' ;输入字符提示信息
Prompt_CNT db 'The specified charactor in th string TABLE: $' ;指定字符出现次数提示信息
Start: push cs
pop ds
push cs
pop es ;使数据段、附加段与代码段同段
cld
Input_Str: Output Prompt_Str ;提示输入字符串
lea dx,TABLE ;字符串缓冲区地址
mov ah,0ah
int 21h
call Output_CTLF ;输出一个回车、换行
lea si,TABLE[1] ;实际输入的字符串长度地址
lodsb ;读入这个长度N
test al,0ffh ;N=0?
jnz Read_Chr ;否,转去输入一个字符
Output No_String ;空字符串提示信息
jmp Input_Str ;重新输入字符串
Read_Chr: Output Prompt_Chr ;提示输入字符
mov ah,1 ;从键盘输入一个字符
int 21h
cmp al,1bh
jz Exit_Proc ;若按键为Esc,则结束程序
cmp al,20h ;控制及通讯字符?
jb Read_Chr ;重新输入字符
call Output_CTLF ;输出一个回车、换行
call Output_CTLF ;输出一个回车、换行
push ax
Output Prompt_CNT ;提示指定字符出现次数提示
pop ax
mov ah,al ;指定的字符送ah保存
lea si,TABLE[1] ;实际输入的字符串长度地址
lodsb ;读入这个长度N
mov cl,al
xor ch,ch ;N=cx
xor bl,bl ;计数器,计数指定字符在字符串中出现的次数
call Find_Chr ;在N个字节数组中查找字符CHAR,并记录该字符出现的次数
mov al,bl
xor ah,ah
call Dec_ASCII ;把AX中的二进制无符号数转换成显式的十进制ASCII码,并送显示屏显示
Exit_Proc: mov ah,4ch ;结束程序
int 21h
TABLE db 255 ; 字符串缓冲区
Code ENDS
END Start ;编译到此结束
汇编语言程序设计
一、
MOV DI,0000H ;让ds:di指向字符串
MOV CX,n ;设置循环次数
MOV AL,'A' ;设置扫描的字母
CLD ;设置df为0
REPNE SCASB ;开始扫描
JZ FOUND ;找到则跳转
MOV DI,00H ;没找到则让di指向字符串开头
FOUND: MOV BX,DI ;让bx记录A所在位置
HLT ;处理器暂停
二、
TEST AX, 0001H ;判断最后一位是否为一
JZ EVEN ;为一,是奇数,跳转
ADD AX,1 ;是偶数,加一
EVEN: SHR AX,1 ;右移一位,相当于除2
三、
MOV CX,100 ;设置循环次数
MOV SI,00FFH ;di指向字符串的前一个字节
L1:INC SI
CMP BYTE PTR[SI],’$’
LOOPNE L1 ;di指向下一个字节,如果它不是$而且循环次数未到,则转到L1继续循环;
SUB SI,0100H
MOV CX,SI
MOV SI,0100H ;指向第一个字符
MOV AL,[SI] ;把第一个字符送入al
DEC CX ;指向前一个字符
L2: INC SI ;指向下一个字符
ADD AL,[SI] ;把字符加到al
LOOP L2 ;如果次数没到则转L2继续
HLT ;处理器暂停
data segment
n db 5
result dw ?
data ends
code segment
assume ds:data,cs:code
start:
mov ax,data
mov ds,ax
mov cl,n
mov ch,0
mov al,1
next:
mul cl
loop next
mov result,ax
mov ax,4c00h
int 21h
code ends
end start
1. 串操作指令、处理器控制指令-位控制指令
在某一字符串中搜寻是否有字符A,若有,则把搜索次数记录下来,送到BX中;若无,则将BX清0。设字符串起始地址偏移量为00H,字符串长度为n。
MOV DI,0000H //字符串初始地址放入寄存器DI中
MOV CX,n //字符串长度放入CX中
MOV AL,'A' //要查找的字母A放入AL中
CLD//清除方向标志位
REPNE SCASB//以上都是指令REPNE SCASB的指令要求。。。可以参考该指令用法,作用是不相等则重复比较
JZ FOUND //有条件跳转转移 CX为零则执行标号FOUND处的指令
MOV DI,00H//赋值DI为00H
FOUND: MOV BX,DI//DI值赋给BX
HLT//停止 关键是REPNE SCASB指令
2.条件转移指令
AX中存放的无符号数,若为偶数,则直接除以2;若为奇数,则加1再除以2。
TEST AX, 0001H //AX中的数与0001H做逻辑与运算 但不影响AX的值
JZ EVEN //如果结果为0则AX中为偶数跳转到EVEN
ADD AX,1 //AX中的数加1
EVEN: SHR AX,1 //AX中的数右移一位 相当于除以2
3. 循环指令
若在存储器的数据段中有100个字节构成的数组,要求从该数组中找出“$”字符,然后将“$”字符前面的所有元素相加,结果保留在AL寄存器中。
MOV CX,100 //将100赋值给计数寄存器CX
MOV SI,00FFH //初始地址00FFH赋值给SI
L1:INC SI //将SI中的值加1
CMP BYTE PTR[SI],’$’ //当前地址的一字节数据与$做比较
LOOPNE L1 //不相等继续执行L1
SUB SI,0100H //SI中的数据减去100
MOV CX,SI //SI 赋值给CX
MOV SI,0100H
MOV AL,[SI] //以SI中的数据做地址寻址找到数据赋值给AL
DEC CX //CX 减去1
L2: INC SI //将SI中的数加1
ADD AL,[SI] 用SI相对寻址得到的数据与AL中的数据相加
LOOP L2 循环执行L2一直到CX为0
HLT
最后这个我不是很明白
我认为该这样写
MOV CX,100
MOV SI,00FFH
L1:INC SI
CMP BYTE PTR[SI],’$’
LOOPNE L1
SUB SI,00FFH //更改了这。。。00FF应该是起始地址 为什么原程序减去的是100呢。。不理解
MOV CX,SI //当前SI值应该是$所在的地址 减去00FFH就成了$之前的字节数 然后赋值给CX
MOV SI,00FFH
MOV AL,[SI]
DEC CX
L2: INC SI
ADD AL,[SI]
LOOP L2
HLT
简单的汇编语言程序设计!加急!
MOV 32H, 30H
MOV A, 30H
CLR C
SUBB A, 31H ;(30H)-(31H)
JC EXIT ;不够减转移
MOV 32H, 31H ;否则31H才是小数
EXIT:
END
---------------------------
2. 将片内RAM单元中 30H~37H 的数据送到片外RAM的 40H~47H。
MOV R0, #30H
MOV R1, #40H
MOV R2, #8
LOOP:
MOV A, @R0
MOVX @R1, A
INC R0
INC R1
DJNZ R2, LOOP
END
汇编语言 秒表程序设计
主程序:
push ds ;保存数据段
mov ax,0000
mov ds,ax ;数据段清零
mov ax,offset irq7 ;取中断程序入口地址
add ax,2000 ;加装时IP=2000地址
mov si,003c ;填8259中断7中断矢量
mov w[si],ax ;填偏移量矢量
mov ax,0000 ;段地址CS=0000H
mov si,003e
mov w[si],ax ;填段地址矢量
pop ds ;弹栈
in al,21 ;读8259中断屏蔽字
and al,7f ;开8259中断7
out 21,al
mov al,b4 ;8253的计数器2为方式2,采用二进制计数,先低后高写入计数值 10110100
out 43,al ;写入方式控制字
mov ax,2e9c 0010 1110 1001 1100B 11932D
out 42,al ;写入低字节计数值 1001 1100
mov al,ah
out 42,al ;写入高字节计数值 0010 1110
mov al,81 ;8255的A口为方式0输出,B口为方式0输出,C口下部输入 1000 0001
out 63,al ;写方式控制字
call first ;调用first子程序,赋计数初值
begi:hlt 延时等待
sti ;开中断
mov ah,01
int 16 ;检测是否按了键盘
jz begi
mov ah,00 ;读键值
int 16
cmp al,0d ;是否按了回车
jnz A1
mov si,4000
not [si+04] ;偏移地址为4004的内存单元内容取反
jmp begi
A1:cmp al,1b ;是否按了ESC键
jnz A2
call first ;重新赋初值,相当于清零
A2:jmp begi
中断程序:
irq7:call disp ;调用disp子程序,用来在数码管显示数据
mov si,4000
cmp [si+04],00 ;判断是否按了第2次回车键
je A4
call addn ;调用addn子程序,用来计数
A4:mov al,20
out 20,al
cli ;关中断
iret ;返回
addn程序:
addn:mov si,4000
add [si+03],01 ;百分之一秒加1
cmp [si+03],0a ;判断是否大于10
jz A5
jmp A9
A5:mov [si+03],00
Add [si+02],01 ;十分之一秒加1
cmp [si+02],0a ;判断是否大于10
jz A6
jmp A9
A6:mov [si+02],00
add [si+01],01 ;秒位加1
cmp [si+01],0a ;判断是否大于10
jz A7
jmp A9
A7:mov [si+01],00
add [si],01 ;十秒位加1
cmp [si],06 ;判断是否大于6
jz A8
jmp A9
A8:mov [si],00 ;大于60:00重新开始
A9: ret
赋初值程序:
first:mov si,4000
mov al,00
mov [si],al
mov [si+01],al
mov [si+02],al
mov [si+03],al
mov [si+04],al
ret
显示程序:
disp:push ax ;保存AX
mov si,4000 ;指向数据缓冲区
mov dl,f7 ;1111 0111 指向数码管
mov al,dl ;al=1111 0111
again:out 60,al ;写端口A
mov al,[si]
mov bx,4100 ;指向数码缓冲区 bx=0100 0001 0000 0000
and ax,00ff ; ax=0000 0000 al
add bx,ax ;得到显示代码 bx=0100 0001 al
mov al,[bx]
out 61,al ;写端口B
call dally :调用延时程序dally
inc si
mov al,dl
test al,01
jz out
ror al,1 ;指向下一个数码管
mov dl,al
jmp again
out: pop ax ;弹出AX
ret
dally:push cx ;延时程序
push ax
mov cx,0010
t1 :mov ax,0010
t2 dec ax
jnz t2
loop t1
pop ax
pop cx
ret
数码缓冲区:
0000:4000 3f,06,5b4f,66,6d,7d,07,7f,6f
二、 设计思想
电子秒表要实现的功能:用键盘中断来控制整个程序,按一下回车键启动电子秒表,再按一下暂停,按一下ESC键清零,用七段数码管显示时间。整个程序涉及到8255、8253与8259三个芯片。8253的OUT2,CLK2分别连接8259的IRQ7与PCLK,8253的GATE2连接正5伏电压,采用计数器2每隔0.01秒产生一次中断并且计数,写入以偏移地址4000H开始的4个内存单元,然后利用8255将内存单元的数据输出到七段数码管。由于键盘中断优先于8259的7号中断,所以程序只有在按一下回车键才启动电子秒表,再按一下暂停,按一下ESC键清零,如果超出了60秒,整个程序自动重新开始。
三、 所用芯片工作原理
8255:接口电路在CPU和I/O设备之间起着信号的变换和传输的作用。 任何接口电路与CPU之间的信息传输方式都是并行的,即CPU与接口电路之间以数据字节/字为单位传送信息。接口电路与I/O设备之间的信息传送方式,有并行和串行两种,相应的接口电路称为并行接口和串行接口。
并行接口是在多根数据线上,以数据字节/字与I/O设备交换信息。在输入过程中,输入设备把数据送给接口,并且使状态线“输入准备好”有效。接口把数据存放在“输入缓冲寄存器”中,同时使“输入回答”线有效,作为对外设的响应。外设在收到这个回答信号后,就撤消数据和“输入准备好”信号。数据到达接口中后,接口会在“状态寄存器”中设置输入准备好标志,或者向CPU发一个中断请求。CPU可用查询方式或中断方式从接口中读取数据。接口中的数据被读取后,接口会自动清除状态寄存器中的标志,且撤消对CPU的中断请求。
在输出过程中,每当输出寄存器可以接收数据,接口就会将状态寄存器中“输出准备好”状态置1或向CPU发一个中断请求,CPU可用查询或中断方式向接口输出数据。当CPU输出的数据到达接口后,接口会清除“输出准备好”状态,把数据送往外设,并向外设发一个“数据输出准备好”信号。外设受到驱动后,便接收数据,并向接口电路发一个“输出回答”信号,接口收到该回答信号后,又将状态寄存器中“输出准备好”置位,以便CPU输出下一个数据。
8253:对CLK信号进行“减1计数”。首先CPU把“控制字”,写入“控制寄存器”,把“计数初始值”写入“初值寄存器”,然后, 定时/计数器按控制字要求计数。计数从“计数初始值 开始,每当CLK信号出现一次,计数值减1,当计数值减为0时,从OUT端输出规定的信号(具体形式与工作模式有关)。当CLK信号出现时,计数值是否减1(即是否计数),受到“门控信号”GATE的影响,一般,仅当GATE有效时,才减1.门控信号GATE如何影响计数操作,以及输出端OUT在各种情况下输出的信号形式与定时/计数器的工作模式有关。
8259:1. IR线上提出了中断请求的中断源,即出现请求,IRR中断请求寄存器(共有8位D7~D0)对应于连接在IR0~IR7线上的外设的中断请求,哪一根输入线有请求,哪一根输入线就置1。
2. 若OCW1(IMR中断屏蔽寄存器)未使该中断请求屏蔽(对应位为0时不屏蔽),该请求被送入PR(优先权分析器)比较。否则,不送入PR比较。
3. PR把新进入的请求与ISR(服务中寄存器)中正在被处理的中断进行比较。如果新进入的请求优先级较低,则8259不向CPU提出请求。如果新进入的请求优先级较高,则8259使INT引脚输出高电平,向CPU提出请求。
4. 如果CPU内部的标志寄存器中的IF(中断允许标志)为0,CPU不响应该请求。若IF=1,CPU在执行完当前指令后,从CPU的INTA引脚上向8259发出两个负脉冲。
5.第一个 INTA负脉冲到达8259时,8259完成以下三项工作:
a.使IRR(中断请求寄存器)的锁存功能失效。这样一来,在IR7~IR0上的请求信号就不会被8259接收。直到第二个INTA负脉冲到达8259时,才又使IRR的锁存功能有效。
b.使ISR(服务中寄存器)中的相应位置1。
c.使IRR中的相应位清0。
6.第二个INTA负脉冲到达8259时,8259完成以下工作:
a.将中断类型码(ICW2中的值)送到数据总线上,CPU将其保存在“内部暂存器”中。
b.如果ICW4(它设定级中断联方式之特定完全嵌套方式,将在8259的工作方式中详述ICW4)中设置了中断自动结束方式,则将ISR的相应位清0。
汇编语言 子程序设计
数放在ax里面
MOV AX,DATAS
MOV DS,AX
mov ax,0f2h
mov cl,4
push ax
shl ax,cl
cmp ah,9
ja n1
add ah,30h
mov dl,ah
mov ah,02h
int 21h
jmp n2
n1:
add ah,37h
mov dl,ah
mov ah,02h
int 21h
n2:
pop ax
and al,0fh
cmp al,9
ja n3
add al,30h
mov dl,al
mov ah,02h
int 21h
jmp n4
n3:
add al,37h
mov dl,al
mov ah,02h
int 21h
n4:
mov ah,4ch
int 21h
上面是16进制输出
1.将AX中的值以十六进制形式显示。
要求:主程序利用寄存器把AX的值传送给子程序。
在子程序中将AX中的值以十六进制形式显示。
=====================================
DATA SEGMENT
D1 DW 13276 ;数: 0~65535
DATA ENDS
;------------------------------
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START:
MOV AX, DATA
MOV DS, AX
;------------------------------
MOV AX, D1 ;取来数字.
CALL DISP_AX
MOV DL, 'H'
MOV AH, 2
INT 21H ;输出H
;------------------------------
MOV AH, 4CH
INT 21H ;返回DOS
;------------------------------
DISP_AX:
MOV BX, 16 ;16进制,要除16
MOV CX, 4 ;求4位16进制数.
ABC:
CWD ;将AX扩展到DX
DIV BX
PUSH DX ;保存余数到堆栈.
LOOP ABC
MOV CX, 4 ;显示4位.
ASD:
POP DX
CMP DL, 10
JB A48
ADD DL, 7
A48:
ADD DL, 48
MOV AH, 2
INT 21H ;输出.
LOOP ASD
RET
;------------------------------
CODE ENDS
END START
===========================
2.编写子程序,完成的功能是将DL中的2位十六进制数转换为对应ASCII码。
说明:入口参数AL=待转换的2位十六进制数
出口参数DX=转换后的ASCII码,(高字节对应高位、低字节对应低位)
举例:若AL=2AH,则DX=3241H。
0----9转换为30H----39H +30H
A---F转换为41H----4FH +30H+7H
;------------------------------
AL_ASC_DX:
MOV AH, 0 ;要除16
MOV CL, 16 ;求16进制数.
DIV CL
CMP AL, 10
JB A48
ADD AL, 7
A48:
ADD AL, 48
MOV DH, AL
CMP AH, 10
JB A482
ADD AH, 7
A482:
ADD AH, 48
MOV DL, AH
RET
;------------------------------
汇编语言程序设计
一.
1. ADD BX,AX 或 ADD BL,AL ;类型配对
2. MOV AX,0A999H
3. MOV AX,0F8H
4. MOV AX,1234H 或 MOV AL,12H
5. MOV AX,[BX]
6. MOV DS,AX ;DS不能直接存立即数
7. ADD [BX],10 ;对的诶
8. PUSH AX ;push不能直接push立即数
9. IN AL,DX
10. OUT 40H ,AL
11. MUL AL ;mul不能直接跟立即数
12. MOV [DI],AX ;mov不能两个都是内存
13. ADD DI,AX
14. MOV DS,AX ;CS不可以改
15. SUB 10[SI],AX ;si di 不可以同时出现
二.
SUB [BP], BX 寄存器间接寻址方式;30400H;
MOV [BX+DI], SI 基址变址寻址方式;10400H;
ADD ES:[SI], DI 寄存器相对寻址方式;20200H;
MOV 10[BX], DI 寄存器相对寻址方式;10100H;
MOV DS:[100H], BX 相对基址变址寻址方式;10100H
三.
3456H;5678H;1234H;5678H;
四.
1234H;2468H;0008H;1008H;0804H;0408H;0508H;0508H
五.
01H,31H,0FFH,00H,78H,56H,FFH,FFH,00H,24H,00H,0BH,00H,0BH,19H,09H,09H
(从左往右地址变大)
AX=3101H,BX=0023H
六.
汇编语言是一种符号语言,他和机器语言几乎一一对应,但在书写中却是用有字符串组成的助记符
。。。。。。。
(希望对你有帮助)
自学汇编的路过~ 楼主,太不厚道了吧,这种东西要自己做的吧。 第一题:我看了前面几个,是两个操作数的位数对不上,不能这样用的··· 其他的 懒得看了,自己慢慢做吧,给五百分也懒得帮你做了,哪有这样的啊! 楼主好懒。
八位和十六位寄存器不能同时运算
一.
1.ADD BX,AX 或 ADD BL,AL ;类型配对
2.MOV AX,0A999H
3.MOV AX,0F8H
4.MOV AX,1234H 或 MOV AL,12H
5.MOV AX,[BX]
6.MOV DS,AX ;DS不能直接存立即数
7.ADD [BX],10 ;对
8.PUSH AX ;push不能直接push立即数
9.IN AL,DX
10.OUT 40H ,AL
11.MUL AL ;mul不能直接跟立即数
12.MOV [DI],AX ;mov不能两个都是内存
13.ADD DI,AX
14.MOV DS,AX ;CS不可以改
15.SUB 10[SI],AX ;si di 不可以同时出现
二.
SUB [BP], BX 寄存器间接寻址方式;30400H;
MOV [BX+DI], SI 基址变址寻址方式;10400H;
ADD ES:[SI], DI 寄存器相对寻址方式;20200H;
MOV 10[BX], DI 寄存器相对寻址方式;10100H;
MOV DS:[100H], BX 相对基址变址寻址方式;10100H
三.
3456H;5678H;1234H;5678H;
四.
1234H;2468H;0008H;1008H;0804H;0408H;0508H;0508H
五.
01H,31H,0FFH,00H,78H,56H,FFH,FFH,00H,24H,00H,0BH,00H,0BH,19H,09H,09H
(从左往右地址变大)
AX=3101H,BX=0023H
六.
1.
汇编语言:(AssemblyLanguage)是面向机器的程序设计语言。
汇编:把汇编语言翻译成机器语言的过程称为汇编。
汇编程序:把汇编语言书写的程序翻译成与之等价的机器语言程序的翻译程序。汇编程序输入的是用汇编语言书写的源程序,输出的是用机器语言表示的目标程序。汇编语言是为特定计算机或计算机系列设计的一种面向机器的语言,由汇编执行指令和汇编伪指令组成。采用汇编语言编写程序虽不如高级程序设计语言简便、直观,但是汇编出的目标程序占用内存较少、运行效率较高,且能直接引用计算机的各种设备资源。它通常用于编写系统的核心部分程序,或编写需要耗费大量运行时间和实时性要求较高的程序段。
2.
3.
单独cmpsb就是逐一比较8个位;加上rep,循环比较,还是比较这8位啊
4.
是指在计算机执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的时间处理程序。待处理完毕后又返回原来被中断处继续执行或调度新的进程执行的过程。
5.
宏和子程序都是为了简化源程序的编写,提高程序的可维护性,但是它们二者之间存在着以下本质的区别:
1、在源程序中,通过书写宏名来引用宏,而子程序是通过CALL指令来调用;
2、汇编程序对宏通过宏扩展来加入其定义体,宏引用多少次,就相应扩展多少次,所以,引用宏不会缩短目标程序;而子程序代码在目标程序中只出现一次,调用子程序是执行同一程序段,因此,目标程序也得到相应的简化;
3、宏引用时,参数是通过“实参”替换“形参”的方式来实现传递的,参数形式灵活多样,而子程序调用时,参数是通过寄存器、堆栈或约定存储单元进行传递的;
4、宏引用语句扩展后,目标程序中就不再有宏引用语句,运行时,不会有额外的时间开销,而子程序的调用在目标程序中仍存在,子程序的调用和返回均需要时间。
总之,当程序片段不长,速度是关键因素时,可采用宏来简化源程序,但当程序片段较长,存储空间是关键因素时,可采用子程序的方法来简化源程序和目标程序。
七.
…………
汇编语言程序设计
; 本程序通过编译,运行正确
Code Segment
Assume CS:Code,DS:Code
ARRAX db 15,23,35,46,51,62,73,84,95,178 ;10个8位无符号位二进制数
Elements equ ($-ARRAX)/Type ARRAX ; 数组元素个数
ARRAY db ? ;平均值
Start: push cs
pop ds
push cs
pop es ;使数据段、附加段与代码段同段
cld
lea si,ARRAX ;数组首地址
mov cx,Elements-1 ; 数组元素个数-1 装入计数寄存器
lodsb ;读入一个元素至AL
Adding: add al,[si]
inc si
loop Adding
mov cx,Elements
xor ah,ah
div cl
mov ARRAY,al
Exit_Proc: mov ah,4ch ;结束程序
int 21h
Code ENDS
END Start ;编译到此结束