如果用汇编语言读写文件,一般要简化这些要求郑纤,比如假设只针对Windows的FAT格式的存储格式,汇编程序需要能解析FAT格式硬盘的存储格式,从FAT格式中能访问到文件实际存储位置,这就使汇编很麻烦了,汇编不是来做这种复杂而人盯丛毕性化的工作的
普通汇编程序要读写硬盘,一般采用无格式的方式,需要自己设计简单的文件管理,这样可以快速简单地保存数据到硬盘中,但保存的数据无法凯芹简单被windows等磁盘 *** 作系统读取,还需要转换才行。
**************************************AT24C04测试程序 供参考
工作频率: 12.000MHz
**************************************
SCL BIT P2.0 AT24C04的时钟线
SDA BIT P2.1 AT24C04的数败备据线
BUF EQU 30H数据缓存区
**************************************
ORG 0
JMP Reset
ORG 100H
Reset:
CALL AT24C04_WritePage 写一页数据
CALL Delay5ms 写一页数据需延时5ms
CALL AT24C04_ReadPage 读一页数据
JMP $
**************************************
向AT24C04写1页(16字节)数据
将TESTDATA开始的16个测试数据写如设备的00~0F地址中
入口参数:无
出口参数:无
**************************************
AT24C04_WritePage:
CALL AT24C04_Start 起始信号
MOV A,#0A0H 发送设备地址+写信号
CALL AT24C04_SendByte 发送
MOV A,#00H 发送存储单元地址
CALL AT24C04_SendByte 发送
MOV R0,#16 16字节计数衫配器
MOV DPTR,#TESTDATA 测试数据首地址
WriteNext:
CLR A 读取测试数据
MOVC A,@A+DPTR
CALL AT24C04_SendByte 写入设备
INC DPTR准备下一个数据的地址
DJNZ R0,WriteNext 判断16字节是否完成
CALL AT24C04_Stop 停止信号
RET
TESTDATA:
DB 000H,011H,022H,033H,044H,055H,066H,077H
DB 088H,099H,0AAH,0BBH,0CCH,0DDH,0EEH,0FFH
**************************************
从AT24C04读取1页(16字节)数据
将设备的00~0F地址中的数据读出存放在DATA区的BUF中
入口参数:无
出口参数:无
**************************************
AT24C04_ReadPage:
CALL AT24C04_Start 起始信号
MOV A,#0A0H 发送设备地址+写信号
CALL AT24C04_SendByte 发送
MOV A,#00H 发送存储单元地址
CALL AT24C04_SendByte 发送
CALL AT24C04_Start 起始信号
MOV A,#0A1H 发送设备地址+读信号
CALL AT24C04_SendByte 发送
MOV R0,#16 16字节计数器
MOV R1,#BUF 数据缓冲区首地址
ReadNext:
CALL AT24C04_RecvByte 读取数据
MOV @R1,A 保存数据察塌毁
CJNE R0,#2,$+3 判断回应ACK还是NAK
CALL AT24C04_SendACK发送应答信号
INC R1 缓冲区地址加1
DJNZ R0,ReadNext判断16字节是否完成
CALL AT24C04_Stop 停止信号
RET
**************************************
延时5微秒
不同的工作环境,需要调整此函数
入口参数:无
出口参数:无
**************************************
Delay5us: 2 当改用1T的MCU时,请调整此延时函数
NOP 1
RET 2
**************************************
延时5毫秒
不同的工作环境,需要调整此函数
入口参数:无
出口参数:无
**************************************
Delay5ms: 2 当改用1T的MCU时,请调整此延时函数
PUSH ACC2
PUSH DPL2
PUSH DPH2
MOV DPTR,#-500 2
Delay5ms1:
NOP 1
NOP 1
NOP 1
NOP 1
INC DPTR2
MOV A,DPL 1
ORL A,DPH 1
JNZ Delay5ms1 2
POP DPH 2
POP DPL 2
POP ACC 2
RET 2
**************************************
起始信号
入口参数:无
出口参数:无
**************************************
AT24C04_Start:
SETB SDA
SETB SCL拉高时钟线
CALL Delay5us 延时
CLR SDA 产生下降沿
CALL Delay5us 延时
CLR SCL 拉低时钟线
RET
**************************************
停止信号
入口参数:无
出口参数:无
**************************************
AT24C04_Stop:
CLR SDA
SETB SCL拉高时钟线
CALL Delay5us 延时
SETB SDA产生上升沿
CALL Delay5us 延时
RET
**************************************
发送应答信号
入口参数:C (0:ACK 1:NAK)
出口参数:无
**************************************
AT24C04_SendACK:
MOV SDA,C 写应答信号
SETB SCL拉高时钟线
CALL Delay5us 延时
CLR SCL 拉低时钟线
CALL Delay5us 延时
RET
**************************************
接收应答信号
入口参数:无
出口参数:C
**************************************
AT24C04_RecvACK:
SETB SCL拉高时钟线
CALL Delay5us 延时
MOV C,SDA 读应答信号
CLR SCL 拉低时钟线
CALL Delay5us 延时
RET
**************************************
向IIC总线发送一个字节数据
入口参数:ACC
出口参数:无
**************************************
AT24C04_SendByte:
PUSH 0
MOV 0,#88位计数器
SendNext:
RLC A 移出数据的最高位
MOV SDA,C 送数据口
SETB SCL拉高时钟线
CALL Delay5us 延时
CLR SCL 拉低时钟线
CALL Delay5us 延时
DJNZ 0,SendNext 判断8位数据是否发送完成
POP 0
JMP AT24C04_RecvACK 接收应答信号
RET
**************************************
从IIC总线接收一个字节数据
入口参数:无
出口参数:ACC
**************************************
AT24C04_RecvByte:
SETB SDA使能内部上拉,准备读取数据
PUSH 0
MOV 0,#88位计数器
RecvNext:
SETB SCL拉高时钟线
CALL Delay5us 延时
MOV C,SDA 读数据口
RLC A 保存数据
CLR SCL 拉低时钟线
CALL Delay5us 延时
DJNZ 0,RecvNext 判断8位数据是否接收完成
POP 0
RET
**************************************
END
感楼主诚意,费了九牛二虎之力,方才完成。不知能否满足要求。本程序通过编译蠢斗,运行正确
Code Segment
Assume CS:Code,DS:Code
CR equ 000DH
LF equ 000AH
KBBack equ 0008H
Name_Len equ 18 用户名最大长度
Pass_Len equ 8 密码最大长度
-------------------------------------
将用户名和密码定义为一个结构类型
User Struc 成绩单结构类型
User_Name db Name_Len dup(?) 用户名
Name_Lenth db ? 用户名实际长度
Pass_Word db Name_Len dup(?) 密码
Pass_Lenth db ? 密码实际长度
User EndS
--------------------帆局-----------------
功能:显示指定地址(Str_Addr)的字符串
入口:
Str_Addr=字符串地址(要求在数据段)
用法: Output Str_Addr
用法举例:Output PromptStr
Output MACRO Str_Addr
lea dx,Str_Addr
mov ah,9
int 21h
EndM
---------------------------------带轿磨----
功能:取光标位置
入口:无
出口:DH=行号,DL=列号
GetCursor Proc Near
PUSH AX
PUSH BX
PUSH CX
PUSH DX
XOR BX,BX
MOV AH,3
INT 10H
MOV Cursor_Row,DH
MOV Cursor_Col,DL
POP DX
POP CX
POP BX
POP AX
RET
Cursor_Row DB ?
Cursor_Col DB ?
GetCursor EndP
-------------------------------------
功能:置光标位置
入口:Cursor_Row=行坐标Cursor_Col: 列坐标)
SetCursor Proc Near
PUSH DX
PUSH CX
PUSH BX
PUSH AX
MOV DH,Cursor_Row
MOV DL,Cursor_Col
XOR BX,BX
MOV AH,2
INT 10H
POP AX
POP BX
POP CX
POP DX
RET
SetCursor EndP
-------------------------------------
窗口上滚指定行数
Roll_Up Proc Near
xor bh,bh 显示页号
mov ah,8 读光标位置的字符和属性
int 10h
mov bh,ah 上滚窗口空行属性
mov cx,100h 左上角坐标
mov al,5
mov dx,54fh 右下角坐标
mov ah,6
int 10h
ret
Roll_Up EndP
-------------------------------------
功能:输入指定位数的用户密码,实际输入的密码字符以“*”显示,并有回空纠错功能
入口:di=密码输入缓冲区地址
出口:AL=实际输入的密码字符数
Input_PassW Proc Near
push di
mov cx,Pass_Len 密码最大长度
@@Input: call GetCursor 取光标位置
mov ah,7 从键盘接受一个字符
int 21h
cmp al,CR 回车符?
jz @@Calc_Chrs 是,结束密码输入,转去计算实际输入的密码字符数
cmp al,KBBack
jz @@KB_Back 若是回空键,重新输入
stosb 保存输入的字符
mov dl,'*'
mov ah,2
int 21h
jmp @@KBBack
@@KB_Back: dec Cursor_Col
inc cx
dec di
@@KBBack: inc Cursor_Col
call SetCursor 置光标位置
loop @@Input 接受下一个数字
@@Calc_Chrs:mov cx,di
pop di
sub cx,di
cmp cl,[si.Pass_Lenth]
jnz @@Pass_Err 密码长度不等
mov cl,[si.Pass_Lenth]
xor ch,ch
push si
lea si,[si.Pass_Word]
cld
repz cmpsb 比较密码是否正确
pop si
jcxz $+4
@@Pass_Err: clc 进位标志复位,表示密码不正确
ret
stc 进位标志置位,表示密码正确
ret
Input_PassW EndP
-------------------------------------
Again_Input Proc Near
Output Input_Again 提示:是否重新输入用户名
mov ah,1 从键盘接受一个字符
int 21h
or al,20h 转换成小写,大小写不敏感
cmp al,'y' 重新输入?
jnz $+7 不
call Roll_Up 窗口上滚指定行数
stc 进位标志置位,表示重复前面的 *** 作
ret
cmp al,'n' 不重新输入?
jnz Again_Input 不是,非有效字母,重新输入
clc 进位标志复位,表示放弃前面的 *** 作
ret
Again_Input EndP
-------------------------------------
Users equ 5 用户数
Even
User_Inform User <'richcon',7,'12345678',8>
User <'WangMing',8,'21345678',8>
User <'ZhangHongQiao',13,'13245678',8>
User <'LiYan',5,'12435678',8>
User <'XuPengYu',12,'12354678',8>
Prompt_User db 'User name: $'
Prompt_Word db 'Pass word: $'
Empty_Error db 7,CR,LF,CR,LF,'User name is empty.$'
Register_No db 7,CR,LF,CR,LF,'No register.$'
Pass_Error db 7,CR,LF,CR,LF,'Pass word error!$'
Welcome db 7,CR,LF,CR,LF,'WELCOME$',0
Input_Again db CR,LF,CR,LF,'Do you input user name again(y/n)?$'
Start: push cs
pop ds 使数据段与代码段同段
push cs
pop es 使附加段与代码段同段
Output Prompt_User 提示输入用户名
call GetCursor 取光标位置
Input_Name: call SetCursor 置光标位置
lea dx,Buffer 数据缓冲区地址
mov ah,0ah 键盘缓冲区输入
int 21h
lea si,Buffer[1] 实际输入的字符数地址
lodsb 取实际输入的字符数
test al,al 空串?
jnz Valid_Test 不是,检测输入的用户是否注册
Output Empty_Error 提示用户名为空
jmp Input_Name 重新输入用户名
Valid_Test: mov cx,Users 注册用户数
lea si,User_Inform 注册用户信息地址
Valid_Test0:cmp al,[si.Name_Lenth] 输入的用户名长度=用户名实际长度?
jnz Next_One 不相等,与下一个注册用户名比较
push cx
push si
lea si,[si.User_Name]
lea di,Buffer[2] 实际输入的用户名地址
mov cl,al
xor ch,ch
cld
repz cmpsb 比较用户名是否已注册
stc 进位标志置位,表示用户名已注册
jcxz $+3
clc 进位标志复位,表示用户名未注册
pop si
pop cx
jc Input_Pass 用户名已注册,转去输入用户密码
Next_One: add si,type User 下一个注册用户信息地址
loop Valid_Test0
Output Register_No 提示:非注册用户
call Again_Input 是否继续
jc Input_Name 进位标志置位,转去重新输入用户名
jmp Exit_Proc 不重新输入用户名,结束程序
Input_Pass: mov word ptr Cursor_Row,1
call SetCursor 置光标位置
Output Prompt_Word 提示输入密码
lea di,Buffer 密码缓冲区地址
call Input_PassW 输入密码
jc @@Welcome 密码输入正确,显示欢迎信息
Output Pass_Error 提示密码输入错误
call Again_Input 是否继续
jc Input_Pass 进位标志置位,转去重新输入密码
jmp Exit_Proc 不重新输入密码,结束程序
@@Welcome: Output Welcome 显示欢迎信息
Exit_Proc: mov ah,4ch 结束程序
int 21h
Buffer db 20 数据缓冲区
Code ENDS
END Start 编译到此结束
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)