|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
106 楼』:
【80x86汇编语言学习笔记】
直接定址表
(到106楼的时候,现在中文打字的速度早已经超过100字以上/每分钟了~:)
描述单元长度的标号
例程:将 code 段中的 a 标号处的 8 个数据累加,结果存储到 b 标号处的字中。
assume cs:code
code segment
a: db 1,2,3,4,5,6,7,8
b: dw 0
start: mov si,offset a
mov bx,offset b
mov cx,8
s: mov al,cs:[si]
mov ah,0
add cs:[bx],ax
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start 程序中,code、a、b、start、s 都是标号,它们仅仅表示了内存单元地址。
数据标号:除了表示内存单元的地址,还表示了内存单元的长度,即表示在此标号处的单元,是一个字节单元还是字单元,还是双字单元)。
使用这种包含单元长度的标号,可以使我们以简洁的形式访问内存中的数据。
它标记了存储数据的单元的地址和长度。
它不同于仅仅表示地址的地址标号。
assume cs:code
code segment
a db 1,2,3,4,5,6,7,8
b dw 0
start: mov si,0
mov cx,8
s: mov al,a[si]
mov ah,0
add b,ax
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start 反汇编上面代码:
0B49:000A BE0000 MOV SI,0000
0B49:000D B90800 MOV CX,0008
0B49:0010 2E CS:
0B49:0011 8A840000 MOV AL,[SI+0000]
0B49:0015 B400 MOV AH,00
0B49:0017 2E CS:
0B49:0018 01060800 ADD [0008],AX
0B49:001C 46 INC SI
0B49:001D E2F1 LOOP 0010
0B49:001F B8004C MOV AX,4C00
0B49:0022 CD21 INT 21 下面程序将 code 段中 a处的8个数据累加,结果存储到b处的dword中,补全程序。
assume cs:code
code segment
a dw 1,2,3,4,5,6,7,8
b dd 0
start: mov si,0
mov cx,8
s: mov ax,a[si]
add word ptr b[0],ax
adc word ptr b[2],0
add si,2
loop s
mov ax,4c00h
int 21h
code ends
end start 在其他段中使用数据标号
在其他段中,我们也可以使用数据标号来描述存储数据的单元和长度。
在后面加有 “:” 的地址标号,只能在代码段中使用,不能在其他段中使用。
将 data 段中 a 标号处的 8 个数据累加,结果存储到 b 标号处的字中。
assume cs:code , ds:data
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
data ends
code segment
start: mov ax,data
mov ds,ax
mov si,0
mov cx,8
s: mov al,a[si]
mov ah,0
add b,ax
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start 如果想在代码段中,直接用数据标号访问数据,则需要用伪指令 assume 将标号所在的段和一个段寄存器联系起来。
否则编译器在编译的时候,无法确定标号的段地址在哪一个寄存器中。
Quote: | assume cs:code , ds:data
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
data ends |
|
seg 操作符,功能为取得某一标号的段地址。
将 data 段中 a 处的 8 个数据累加,结果存储到 b 处的字中,补全程序。
assume cs:code , ds:data
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
data ends
code segment
start: mov ax,data
mov ds,ax
mov si,0
mov cx,8
s: mov al,a[si]
mov ah,0
add b,ax
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start
Quote: | -d ds:0
0B49:0000 01 02 03 04 05 06 07 08-24 00 00 00 00 00 00 00 |
|
直接定址表
编写程序,以十六进制的形式在屏幕中间显示给定的 Byte 型数据。
assume cs:code
code segment
start: mov al,0abh
call showbyte
mov ax,4c00h
int 21h
showbyte: jmp short show
table db '0123456789ABCDE'
show: push bx
push es
mov ah,al
shr ah,1
shr ah,1
shr ah,1
shr ah,1
and al,00001111b
mov bl,ah
mov bh,0
mov ah,table[bx]
mov bx,0b800h
mov es,bx
mov es:[160*12+40*2],ah
mov bl,al
mov bh,0
mov al,table[bx]
mov es:[160*12+40*2+2],al
pop es
pop bx
ret
code ends
end start 利用表,在两个数据集合之间建立一种映射关系,可以用查表的方法根据给出的数据得到其在另一集合的对应数据。
1) 为了算法的清晰和简洁
2) 为了加快运算速度
3) 为了使程序易于扩充
程序入口地址的直接定址表
可以在直接定址表中存储子程序的地址,从而方便实现不同子程序的调用。
实现一个子程序 setscreen,为显示输出提供如下功能:
1) 清屏
2) 设置前景色
3) 设置背景色
4) 向上滚动一行
入口参数说明:
1) 用ah寄存器传递功能号:
0 表示清屏
1 表示设置前景色
2 表示设置背景色
3 表示向上滚动一行
2) 对2、3号功能,用al传送颜色值。(AL)={0,1,2,3,4,5,6,7}
各种功能的实现:
1) 清屏: 将显存中当前屏幕中的字符设为空格符
2) 设置前景色: 设置显存中当前屏幕中处于奇地址的属性字节:0、1、2位
3) 设置背景色: 设置显存中当前屏幕中处于奇地址的属性字节:4、5、6位
4) 向上滚动一行: 依次将第n+1行的内容复制到第n行处;最后一行为空。
assume cs:code
code segment
start: mov ah,0 ; 调 segscreen 子程序的 0 号功能 - 清屏
call segscreen
mov ah,1 ; 调 segscreen 子程序的 1 号功能 - 设前景
mov al,1
call segscreen
mov ah,2 ; 调 segscreen 子程序的 2 号功能 - 设背景
mov al,7
call segscreen
mov ah,3 ; 调 segscreen 子程序的 3 号功能 - 上滚一行
mov al,4
call segscreen
mov ax, 4c00h
int 21h
segscreen: jmp short set ; 所有子功能调用索引表 (入口)
table: dw sub1, sub2, sub3, sub4
;----------------------------------------------------
; 0清屏 1设前景 2设背景 3上滚一行
;----------------------------------------------------
set: push bx
cmp ah,3 ; 判断功能号是否大于3
ja sret
mov bl,ah
mov bh,0
add bx,bx ; 根据ah中的功能号计算对应子程序在table表中的偏移地址
call word ptr table[bx] ; 调用对应的功能子程序
sret: pop bx
ret
sub1: push bx ; 0号子功能: 清屏
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0
mov cx,2000
sub1s: mov byte ptr es:[bx],' '
add bx,2
loop sub1s
pop es
pop cx
pop bx
ret
sub2: push bx ; 1号子功能: 设置前景色
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
sub2s: and byte ptr es:[bx],11111000b
or es:[bx],al
add bx,2
loop sub2s
pop es
pop cx
pop bx
sub3: push bx ; 2号子功能: 设置背景色
push cx
push es
mov cl,4
shl al,cl
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
sub3s: and byte ptr es:[bx],10001111b
or es:[bx],al
add bx,2
loop sub3s
pop es
pop cx
pop bx
ret
sub4: push cx ; 3号子功能: 屏幕向上滚动一行
push si
push di
push es
push ds
mov si,0b800h
mov es,si
mov ds,si
mov si,160 ; 从第 n+1 行传送到第 n 行
mov di,0
cld
mov cx,24 ; 共传送屏幕 24 行数据
sub4s: push cx
mov cx,160
rep movsb
pop cx
loop sub4s
mov cx,80
mov si,0
sub4s1: mov byte ptr [160*24+si],' '
add si,2
loop sub4s1
pop ds
pop es
pop di
pop si
pop cx
ret
code ends
end start 编写包含多个功能子程序的中断例程
安装一个新的 int 7ch 中断例程,为显示输出提供如下功能子程序:
1) 清屏
2) 设置前景色
3) 设置背景色
4) 向上滚动一行
入口参数说明:
1) 用 ah 寄存器传递功能号:
0 表示清屏
1 表示设置前景色
2 表示设置背景色
3 表示向上滚动一行
2) 对于2、3号功能,用 al 传递颜色值,(al)={0,1,2,3,4,5,6,7}
assume cs:code
code segment
;************************************************************
; int7ch 安装代码
;************************************************************
start: mov ax,cs
mov ds,ax
mov si,offset int7ch
mov ax,0
mov es,ax
mov di,200h
mov cx,offset int7ch_end - offset int7ch
cld
rep movsb
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0
mov ax,4c00h
int 21h
;************************************************************
; int7ch 中断例程
;************************************************************
int7ch: jmp short set
;table dw sub1,sub2,sub3,sub4 ; table = 202h
; 编译器在编译的时候认为 table 是上面(中断安装程序)的 cs 地址,
; 而无法定位 table 在 200h 的基础上的偏移,所以暂时先Debug出子程序偏移填入 :(
table dw 021dh, 0238h,0256h,0278h
set: push bx
cmp ah,3
ja sret
mov bl,ah
mov bh,0
add bx,bx
call word ptr cs:[bx].202h
sret: pop bx
iret
sub1: push bx ; int 7ch 0 号子功能:清屏
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0
mov cx,2000
sub1s: mov byte ptr es:[bx],' '
add bx,2
loop sub1s
pop es
pop cx
pop bx
ret
sub2: push bx ; int 7ch 1 号子功能:设置前景色
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
sub2s: and byte ptr es:[bx],11111000b
or es:[bx],al
add bx,2
loop sub2s
pop es
pop cx
pop bx
ret
sub3: push bx ; int 7ch 2 号子功能:设置背景色
push cx
push es
mov cl,4
shl al,cl ; al=xxx0000b
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
sub3s: and byte ptr es:[bx],10001111b
or es:[bx],al
add bx,2
loop sub3s
pop es
pop cx
pop bx
ret
sub4: push cx
push ds
push es
push si
push di
mov si,0b800h
mov ds,si
mov es,si
mov si,160 ; 0-159 = 第1行, 160 = 第2行第0列
mov di,0
cld
mov cx,24 ; 处理 24 行
sub4s: push cx
mov cx,160 ; 要复制一行的内容,共160字节
rep movsb
pop cx
loop sub4s
mov cx,160 ; 清除最后一行内容,因其已复制到上一行了。
sub4s1: mov byte ptr [160*24+si],' '
add si,2
loop sub4s1
pop di
pop si
pop es
pop ds
pop cx
ret
int7ch_end: nop
code ends
end start 遇到一个问题,在上面代码的 int 7ch 子程序的注解处。
暂时解决不了,不知道哪个宏指令可以让编译器认为 table 要从 200h 处为基址计算偏移(实际 table 应为 202h)。
;table dw sub1,sub2,sub3,sub4 ; table = 202h
; 编译器在编译的时候认为 table 是上面(中断安装程序)的 cs 地址,
; 而无法定位 table 在 200h 的基础上的偏移,所以暂时先Debug出子程序偏移填入 :( 关于数据标号与地址标号的区别分析
Quote: | start: jmp short do0
top dw 0
top2: dw 0
do0: mov bx,top
mov ax,offset top2 |
|
分析过程
Quote: | C:\Masm50>debug noname.exe
-r
AX=0000 BX=0000 CX=003D DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0B39 ES=0B39 SS=0B49 CS=0B49 IP=0000 NV UP EI PL NZ NA PO NC
0B49:0000 EB04 JMP 0006
-u
0B49:0000 EB04 JMP 0006
0B49:0002 0000 ADD [BX+SI],AL
0B49:0004 0000 ADD [BX+SI],AL
0B49:0006 2E CS:
0B49:0007 8B1E0200 MOV BX,[0002]
0B49:000B B80400 MOV AX,0004
0B49:000E B001 MOV AL,01
0B49:0010 8800 MOV [BX+SI],AL
0B49:0012 2E CS:
0B49:0013 FF060200 INC WORD PTR [0002]
0B49:0017 2E CS:
0B49:0018 8B1E0200 MOV BX,[0002]
0B49:001C B002 MOV AL,02
0B49:001E 8800 MOV [BX+SI],AL
-t
AX=0000 BX=0000 CX=003D DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0B39 ES=0B39 SS=0B49 CS=0B49 IP=0006 NV UP EI PL NZ NA PO NC
0B49:0006 2E CS:
0B49:0007 8B1E0200 MOV BX,[0002] CS:0002=0000
-t
AX=0000 BX=0000 CX=003D DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0B39 ES=0B39 SS=0B49 CS=0B49 IP=000B NV UP EI PL NZ NA PO NC
0B49:000B B80400 MOV AX,0004
-t
AX=0004 BX=0000 CX=003D DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0B39 ES=0B39 SS=0B49 CS=0B49 IP=000E NV UP EI PL NZ NA PO NC |
|
当操作数据标号时,是在操作数据标号所示地址中的内容,它也代表长度。
如果 inc 它,则是在 inc 数据标号所示地址中的内容的值递增。
当操作地址标号时,是在操作它的偏移量。
[ Last edited by redtek on 2007-1-18 at 01:42 PM ]
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-1-14 12:07 |
|
|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
107 楼』:
【80x86汇编语言学习笔记】
使用BIOS进行键盘输入和磁盘读写
) 键盘输入引发 9 号中断,BIOS提供了 int 9 中断例程。
) CPU在9号中断发生后,执行 int 9中断例程,从60H端口读出扫描码,并将其转化为相应的ASCII码或状态信息。
它们存储在指定空间(键盘缓冲区或状态字节)中。
) 在CPU执行完INT9中断例程后,都放到了键盘缓冲区中。
键盘缓冲区中有16个字单元,可以存储15个按键的扫描码和对应的ASCII码。
) 键盘缓冲区是用环形队列结构管理的内存区。
BIOS的INT9中断例程和INT16H中断例程是一对相互配合的程序。
INT9中断例程向键盘缓冲区中写入。
INT16H中断例程从键盘缓冲区中读了。
例程:接收用户的键盘输入,输入r,将屏幕上的字符设置为红色。
输入g,将屏幕上的字符设置为绿色。输入b,设置为蓝色。
assume cs:code
code segment
start: mov ah,0
int 16h
mov ah,1
cmp al,'r'
je red
cmp al,'g'
je green
cmp al,'b'
je blue
jmp short sret
red: shl ah,1 ; 技巧: 001 左移1后位再被green左移1位,值为100(红色)
green: shl ah,1 ; 如果选择 g ,则只左移一位: 001 左移1位为: 010(绿色)
blue: mov bx,0b800h ; 因 ah默认前面设置为1 ,所以选择b时直跳这里,001本身就是(蓝色)
mov es,bx
mov bx,1
mov cx,2000
s: and byte ptr es:[bx],11111000b
or es:[bx],ah
add bx,2
loop s
sret: mov ax,4c00h
int 21h
code ends
end start 字符串的输入
最基本的字符串输入程序,需具备以下功能:
1) 在输入的同时需要显示这个字符串
2) 一般在输入回车符后,字符串输入结束
3) 能够删除已经输入的字符
编写一个接收字符串的输入子程序,实现上面三个基本功能。
(DH)、(DI)=字符串在屏幕上显示的行、列位置。
DS:SI 指向字符串存储的空间,字符串以0为结尾符。
字符串的存储空间是一个字符栈,字符栈中的所有字符,从栈底到栈顶,组成一个字符串。
程序处理过程:
1) 调用 int 16h 读取键盘输入
2) 如果是字符,进入字符栈,显示字符栈中所有字符;继续执行1
3) 如果是退格键,从字符栈中弹出一个字符,显示字符栈中所有字符;继续执行1
4) 如果是Enter键,向字符栈中压入0,返回。
子程序:字符栈的入栈、出栈和显示
参数说明:(AH)=功能号: 0表示入栈,1表示出栈,2表示显示
DS:SI 指向字符栈空间
对于0号功能: (AL)=入栈字符
对于1号功能: (AL)=返回的字符
对于2号功能: (DH)、(DL)=字符串在屏幕上显示的行、列位置
assume cs:code
data segment
db 256 dup (0)
data ends
code segment
start: mov ax,data
mov ds,ax
call getstr ; 调用字符串接收子程序
mov ax,4c00h
int 21h
getstr: push ax ; 接收字符串输入子程序
push ds
push es
getstrs: mov ah,0
int 16h
cmp al,20h
jb nochar ; ASCII码小于0,说明不是字符
mov ah,0
call charstack ; Call子程序:字符入栈
mov ah,2
call charstack ; 显示栈中的字符
jmp getstrs ; 继续等待从键盘输入的字符
nochar: cmp ah,0eh ; 退格键扫描码
je backspace
cmp ah,1ch ; 回车键扫描码
je enter
jmp getstrs ; 继续等待接收字符
backspace: mov ah,1
call charstack ; 字符出栈(删掉了一个字符)
mov ah,2
call charstack ; 显示栈中的字符
jmp getstrs
enter: mov al,0
mov ah,0
call charstack ; 0入栈
; mov ah,2
; call charstack ; 显示栈中的字符
pop es
pop ds
pop ax
ret
charstack: jmp short charstart
table dw charpush,charpop,charshow
top dw 0
charstart: push bx
push dx
push di
push es
cmp ah,2
ja sret
mov bl,ah
mov bh,0
add bx,bx
jmp word ptr table[bx]
charpush: mov bx,top ; 0号功能: 字符入栈
mov [si][bx],al
inc top
jmp sret
charpop: cmp top,0 ; 1号功能: 字符出栈
je sret ; 如果已是栈顶,则返回
dec top ; 否则栈顶减1表示已出栈
mov bx,top
mov al,[si][bx]
jmp sret
charshow: mov bx,0b800h ; 2号功能: 显示字符
mov es,bx
mov al,160
mov ah,0
mul dh ; dh=行(dh*160), dl=列
mov di,ax
add dl,dl ; n列总字符数
mov dh,0
add di,dx
mov bx,0 ; 清零
charshows: cmp bx,top
jne noempty
mov byte ptr es:[di],' '
jmp sret
noempty: mov al,[si][bx]
mov es:[di],al
mov byte ptr es:[di+2],' '
inc bx
add di,2
jmp charshows
sret: pop es
pop di
pop dx
pop bx
ret
code ends
end start [ Last edited by redtek on 2007-1-16 at 09:55 PM ]
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-1-15 12:33 |
|
|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
108 楼』:
【80x86汇编语言学习笔记】
看 本是 大师的贴子跟着学~:)
34字节DOS EXE文件,最短了?
http://www.cn-dos.net/forum/viewthread.php?tid=26748&fpage=1
操作步骤
Quote: | C:\Masm50\temp>DEBUG
-N P
-L
-R
AX=0000 BX=0000 CX=0204 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0AF5 ES=0AF5 SS=0AF5 CS=0AF5 IP=0100 NV UP EI PL NZ NA PO NC
0AF5:0100 4D DEC BP
-RIP
IP 0100
:0
-D
0AF5:0100 4D 5A 04 00 02 00 00 00-20 00 00 00 FF FF 00 00 MZ...... .......
0AF5:0110 00 00 ED 36 00 00 00 00-1E 00 00 00 01 00 00 00 ...6............
0AF5:0120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0AF5:0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0AF5:0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0AF5:0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0AF5:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0AF5:0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
-E 0120 B4 4C CD 21
-E 0104 01
-E 0108 02
-D CS:100
0AF5:0100 4D 5A 04 00 01 00 00 00-02 00 00 00 FF FF 00 00 MZ..............
0AF5:0110 00 00 ED 36 00 00 00 00-1E 00 00 00 01 00 00 00 ...6............
0AF5:0120 B4 4C CD 21 00 00 00 00-00 00 00 00 00 00 00 00 .L.!............
0AF5:0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0AF5:0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0AF5:0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0AF5:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0AF5:0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
-RCX
CX 0204
:24
-W
Writing 00024 bytes
-Q |
|
修改后的保留文件头为 32 字节,加上所写的指令为4字节(mov ah,4ch 和 int 21h),一共占了32+4=36字节~:)
Debug移动代码到某个指定的内存区的命令给忘了,哈哈……
关于修改 04h 与 08h 文件头的内容还不清楚,现在去找 .exe 文件头的资料~:)))
(在本是大师贴子的第4楼关于文件结构的内容)
(http://www.cn-dos.net/forum/redirect.php?fid=6&goto=lastpost)
相关资料:文件格式
(以下节选出自 http://db.kingsoft.com/lianzai/3.2.shtml - 《数量最多的病毒--文件型病毒》一文
Quote: | 可执行文件格式:
在DOS环境下有四种基本的可执行文件格式:
批处理文件,是以.BAT结尾的文件,在BAT文件中可以包括一些DOS命令,以及在批处理文件中调用其它的可执行文件;批文件还有一些简单的流程控制功能,可以实现循环、条件判断等简单的编程工作。
设备驱动文件,是以.SYS结尾的文件,比如说CONFIG.SYS和IO.SYS等,是DOS操作系统使用的设备驱动程序。
COM文件,是以.COM结尾的纯代码文件。没有文件头部分,缺省的总是从16进制的100H处开始执行,没有重定位项,这也限制了它的所有代码和数据必须控制在64K以内。
EXE文件,是以.EXE结尾的文件,这种文件以英文字母“MZ”开头,通常我们称之为MZ文件。MZ文件有一个文件头,用来指出每个段的定义,以及重定位表。.EXE文件摆脱了代码大小最多不能超过64K的限制,是DOS下最主要的文件格式。
在视窗3.0和视窗3.1版本中,微软推出了一种新的可执行文件格式,在MZ文件头之后又有一个以NE开始的文件头,我们称之为NE文件。由于视窗的可执行文件同DOS相比增加了很多内容,如资源、动态库...。NE格式表现极为复杂,NE格式文件装载程序读取磁盘上的文件后,需要在内存中组装成一个完全不同的数据结构然后开始运行。
在视窗32位平台(版本9x和版本NT/2000系列),微软又推出了一种新的可执行文件格式,可移植的可执行文件(Portable Executable File)格式。它同NE格式不同的是在MZ文件头之后是一个以“PE”开始的文件头。PE文件格式是从COFF(一个在Unix世界中广泛使用的通用二进制文件格式)的对象格式发展而来的,它同NE格式相比是进了一大步,其文件在磁盘中的格式同内存中的格式区别不大,装载程序实现起来相当简单。
在视窗32位环境下,微软还有一种应用比较少的可执行文件格式:线性可执行文件(Linear Executable),主要用于设备驱动程序VXD,这种格式是微软和IBM共同开发的,也是IBM的OS/2操作系统使用的可执行文件格式。 |
|
(一知半解)
[ Last edited by redtek on 2007-1-20 at 10:24 PM ]
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-1-17 01:32 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
109 楼』:
Quote: | Originally posted by redtek at 2007-1-16 12:32:
修改后的保留文件头为 32 字节,加上所写的指令为4字节(mov ah,4ch 和 int 21h),一共占了32+4=26字节~:) |
|
呵呵,学汇编学昏了吧?
|
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。 |
|
2007-1-17 09:25 |
|
|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
110 楼』:
多谢namejm兄提醒,“32+4=26字节”错误更正了~:)
这错误看上去真可乐,哈哈哈………
[ Last edited by redtek on 2007-1-16 at 08:48 PM ]
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-1-17 09:44 |
|
|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
111 楼』:
【80x86汇编语言学习笔记】
磁盘操作
常用的 3.5 寸软盘分为上下两面,每面有80个磁道,每个磁道又分为18个扇区,每个扇区的大小为512B。
2面*80磁道*18扇区*512B=1474560
磁盘的实际访问由磁盘控制器进行,通过控置磁盘控制器来访问磁盘。只能以扇区为单位对磁盘进行读写。
在读写扇区时,要给出面号、磁道号和扇区号。
面号和磁道号从0开始,扇区号从1开始。
BIOS提供了对扇区进行读写的中断例程 int 13H。
读取0面0道1扇区的内容到 0:200
assume cs:code
code segment
start: mov ax,0 ; 起始时寄存器会被自动初始化,也可以不写这句
mov es,ax
mov bx,200h ; es:bx 指向接收从扇区读入数据的内存区
mov al,1 ; 读取扇区数
mov ch,0 ; 磁道号
mov cl,1 ; 扇区号
mov dh,0 ; 磁头号
mov dl,0 ; 驱动器号
mov ah,2
int 13h
mov ax,4c00h
int 21h
code ends
end start 将 0:200 中的内容写入0面0道1扇区
assume cs:code
code segment
start: mov ax,0
mov es,ax
mov bx,200h
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,0
mov ah,03
int 13h
mov ax,4c00h
int 21h
code ends
end start 将当前屏幕的内容保存在磁盘上
assume cs:code
code segment
start: mov ax,0b800h
mov es,ax
mov bx,0
mov al,8
mov ch,0
mov cl,1
mov dh,0
mov dl,0
mov ah,3
int 13h
mov ax,4c00h
int 21h
code ends
end start 1.44 - 2880个扇区,从0编号:逻辑扇区为 0~~2879
0面79道18扇区,计算逻辑扇区号:(0*80+79)*18+18-1
[ Last edited by redtek on 2007-1-18 at 12:40 PM ]
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-1-18 03:34 |
|
|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
112 楼』:
【80x86汇编语言学习笔记】
中断例程 INT 21H 3F号子功能调用来操作DOS 管道。
通过编程的方式读取一个程序通过管道“发送”过来的内容。
参考资料: http://support.microsoft.com/kb/46376/zh-cn 来自微软网站。
上面链接中所参考的示例代码为: QuickBasic 程序(调用汇编代码完成读取管道内容)
中断 21 Hex, 以函数 3F, 需要注册参数来传递:
AH 编号 3F Hex, = 函数。
BX Handle = 到文件或设备。
CX =: 为要读取字节数。
DS = 非缓冲区区段。 缓冲区将是一个字符串。
DX = 非缓冲区区偏移。 如果 CF=0 , AX=实际读取的字节数
CF=1 , AX=出错代码
连蒙带猜的Debug试验过程……
Quote: | -u
0B39:0100 B80000 MOV AX,0000
0B39:0103 8ED8 MOV DS,AX
0B39:0105 BA0002 MOV DX,0200
0B39:0108 B95000 MOV CX,0050
0B39:010B 31C0 XOR AX,AX
0B39:010D B43F MOV AH,3F
0B39:010F BB0000 MOV BX,0000
0B39:0112 CD21 INT 21
0B39:0114 90 NOP
(上面 BX 寄存器内应存放文件句柄,按照上面资料的代码注释上说:)
(inregs.bx = 0 ' The is the handle to the CON device is 0 )
-g 114
My is China.
(在这里居然让我输入东东,哈哈……)
(看来我在这里输入的内容会被接收程序当做从管道过来的内容而接收掉)
(它被接收到了 DS:DX 文件数据缓冲区这里所定义的地址)
(那个 “My is China.” 是我输入的内容)
AX=000E BX=0000 CX=0050 DX=0200 SP=FFFE BP=0000 SI=0000 DI=0000
DS=0000 ES=0B39 SS=0B39 CS=0B39 IP=0114 NV UP EI PL ZR NA PE NC
0B39:0114 90 NOP
(输入的内容被读到了这里)
-d ds:200
0000:0200 4D 79 20 69 73 20 43 68-69 6E 61 2E 0D 0A 00 00 My is China.....
0000:0210 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0220 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0230 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0240 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0250 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0260 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0270 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ |
|
通过管道实验过程:
C:\TEMP\str>debug
-d 0:200 22F
0000:0200 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0210 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0220 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
-q
C:\TEMP\str>copy con demo.txt
My name is Redtek.
Phone: 12345678
hahahaha...
^Z
已已复复制制 1 个个文文件件。。
C:\TEMP\str>type demo.txt | rCON.com
C:\TEMP\str>debug
-d 0:200 22F
0000:0200 4D 79 20 6E 61 6D 65 20-69 73 20 52 65 64 74 65 My name is Redte
0000:0210 6B 2E 0D 0A 50 68 6F 6E-65 3A 20 31 32 33 34 35 k...Phone: 12345
0000:0220 36 37 38 0D 0A 68 61 68-61 68 61 68 61 2E 2E 2E 678..hahahaha...
-q 在内存 0:200H 处,它们全被存到了自定义的( DS:DX )文件数据缓冲区内。
上面的实验过程是调用了 int 21 中断例程的 3FH 子功能来读取通过管道送过来的字符串。支持多行字符串,以 0DH 0AH 为回车换行。
也就是说,这样的原理可以应用在批处理中:
比如将输出的内容暂存在指定的内存中,而不是磁盘上(代替批处理所生成的临时文件)。
当需要的时候再取回来或是通过某种内存操作来分割(如我就想要第3行字符串,其它的都不要)等操作。
(一知半解)
[ Last edited by redtek on 2007-1-20 at 10:23 PM ]
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-1-19 06:58 |
|
|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
113 楼』:
【80x86汇编语言学习笔记】
字符串操作
方便的 BIOS int 10 -- 13号子功能调用
在第10行(行从0起,实为第11行),第0列(实为第1列)显示字符串:
assume cs:code
code segment
start: jmp short do
msg: db "my name is redtek!"
line: nop
do: mov ax,seg msg
mov es,ax
mov bp,offset msg
mov al,1 ; 光标跟随移动
mov dh,10 ; 10 行
mov dl,0 ; 0 列
mov bh,0 ; 页号
mov bl,2 ; 颜色
mov cx,offset line - offset msg
mov ah,13h
int 10h
mov ax,4c00h
int 21h
code ends
end start 上面显示字符串使用了 BIOS 功能调用。
自动从 DS:SI 装入字符到 AL 寄存器:
LODSB 指令,将 DS:SI 地址中的 byte 字符装入 AL 寄存器,然后 SI+1,每次执行 LODSB 指令时均会如此,方便了字符串的传送。
Quote: | C:\Masm50>debug
-e 0:200 "My name is Redtek!"
-a
0AF6:0100 mov ds,ax
0AF6:0102 mov si,200
0AF6:0105 lodsb
0AF6:0106 lodsb
0AF6:0107 lodsb
0AF6:0108
-r
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0AF6 ES=0AF6 SS=0AF6 CS=0AF6 IP=0100 NV UP EI PL NZ NA PO NC
0AF6:0100 8ED8 MOV DS,AX
-t
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0000 ES=0AF6 SS=0AF6 CS=0AF6 IP=0102 NV UP EI PL NZ NA PO NC
0AF6:0102 BE0002 MOV SI,0200
-t
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0200 DI=0000
DS=0000 ES=0AF6 SS=0AF6 CS=0AF6 IP=0105 NV UP EI PL NZ NA PO NC
0AF6:0105 AC LODSB
-t
AX=004D BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0201 DI=0000
DS=0000 ES=0AF6 SS=0AF6 CS=0AF6 IP=0106 NV UP EI PL NZ NA PO NC
0AF6:0106 AC LODSB
-t
AX=0079 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0202 DI=0000
DS=0000 ES=0AF6 SS=0AF6 CS=0AF6 IP=0107 NV UP EI PL NZ NA PO NC
0AF6:0107 AC LODSB
-t
AX=0020 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0203 DI=0000
DS=0000 ES=0AF6 SS=0AF6 CS=0AF6 IP=0108 NV UP EI PL NZ NA PO NC
0AF6:0108 29C0 SUB AX,AX
-q |
|
获得命令行输入的参数(类似于批处理中的: %1 %2 %3 ....)
命令行输入的参数位于: DS:0081H 处,以 0AH 结束。
assume cs:code
code segment
start: mov si,0081h ; 定位到命令行参数 (psp处偏移量 81h)
s: lodsb
cmp al,0dh
je short view ; 如果命令行参数结束,则显示它
jmp short s
view: mov byte ptr [si],24h
mov ah,9
mov dx,0081h
int 21h
mov ax,4c00h
int 21h
code ends
end start [ Last edited by redtek on 2007-1-21 at 01:39 PM ]
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-1-21 11:27 |
|
|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
114 楼』:
【Windows环境下32位汇编语言学习笔记】
API原型中前缀详细解释:
a Array 数组
b BOOL (int) 布尔(整数)
by Unsigned Char (Byte) 无符号字符(字节)
c Char 字符(字节)
cb Count of bytes 字节数
cr Color reference value 颜色(参考)值
cx Count of x (Short) x的集合(短整数)
dw DWORD (unsigned long) 双字(无符号长整数)
f Flags (usually multiple bit values) 标志(一般是有多位的数值)
fn Function 函数
g_ global 全局的
h Handle 句柄
i Integer 整数
l Long 长整数
lp Long pointer 长指针
m_ Data member of a class 一个类的数据成员
n Short int 短整数
p Pointer 指针
s String 字符串
sz Zero terminated String 以0结尾的字符串
tm Text metric 文本规则
u Unsigned int 无符号整数
ul Unsigned long (ULONG) 无符号长整数
w WORD (unsigned short) 无符号短整数
x,y x, y coordinates (short) 坐标值/短整数
v void 空 API的参考手册中的函数原型为匈牙利表示法。
[ Last edited by redtek on 2007-1-20 at 10:35 PM ]
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-1-21 11:33 |
|
|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
115 楼』:
【MS-DOS操作系统学习笔记】
引导扇区
当计算机从软盘启动,BIOS把引导盘中第1扇区载入地址为 0000:7c00 处的内存中。然后BIOS跑到 0X7C00 处开始执行引导扇区中的代码。
引导扇区的代码完成将整个操作系统载入到计算机内存并开始操作系统的引导。
第1扇区,就是 DOS Boot Record(DOS引导扇区)。
(待续……)
[ Last edited by redtek on 2007-1-25 at 08:14 PM ]
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-1-24 06:26 |
|
|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
116 楼』:
彩色仿DOS窗口
这个彩色仿DOS窗口是跟lxmxn兄学的~:)))
而且用这种颜色、背景表示DOS命令即酷又生动,更接近真实~~~
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-1-25 02:57 |
|
|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
117 楼』:
【MS-DOS操作系统学习笔记】
文件操作
将字符串写入文件内。
assume cs:code , ds:data
data segment
file db 'c:\temp\1.txt',0 ; 定义被创建的文件名称
buf db 'This is a test!' ; 写入文件的内容
err_msg db 0ah,'Error!','$' ; 出错时的提示信息
ok_msg db 0ah,'Ok!','$' ; 操作成功后的提示
handle dw ?
data ends
code segment
start: mov ax,data
mov ds,ax
mov dx,offset file
mov cx,0
mov ah,3ch
int 21h ; 创建文件
jc error ; 如果创建出错,转error处
mov handle,ax ; 保存文件句柄
mov bx,ax ; 写文件时文件句柄必须在bx中
mov cx,16 ; 写文件长度
mov dx,offset buf ; 要写入文件的内容首地址
mov ah,40h
int 21h
jc error ; 如果写文件出错,则转error处
mov bx,handle
mov ah,3eh
int 21h ; 关闭文件
jc error ; 如果关闭文件出错,转error
mov dx,offset ok_msg
mov ah,9
int 21h ; 操作成功显示
jmp end1
error: mov dx,offset err_msg
mov ah,9
int 21h
end1: mov ah,4ch
int 21h
code ends
end start int21 DOS功能调用: 40H 写文件
3FH 读文件
3EH 关闭文件
41H 删除文件
……
[ Last edited by redtek on 2007-1-26 at 04:08 PM ]
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-1-27 05:03 |
|
|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
118 楼』:
【Windows32位汇编语言学习笔记】
建立编程环境
Win32可执行文件叫做PE文件。
PE文件的基本结构和DOS可执行文件有很大不同。它把程序中的不同部分分成各种节区(Section),其中可以有一个节区是放置各种资源,如:菜单、对话框、位图、光标、图标和声音等。
可供选择的不同编译器: MASM,TASM,NASM
根据以上编译的优缺点最后选择不同工具软件集合方式开发 Win32 汇编:
汇编编译器: MASM软件包中的 ML.EXE 做为 Win32 汇编编译器
资源编译器: 使用 Microsoft Visual Studio 中的 RC.EXE 和 LINK.EXE……
……
目前已被 Steve Hutchesson 缩合创建的开发软件包名为 MASM32,内收集了合适的工具软件、收集导入库、整理出完整的头文件、收集了来自全世界各地Win32汇编爱好者发布的源程序、帮助文档、IDE开发环境……
MASM32软件包使汇编不再只用来编写简单的程序和少量的核心模块,它的目标完全是为了用汇编写出专业的大型程序。
MASM32软件包的官方站点(在此下载):
http://www.movsd.com
支持OS版本:Win2000 and later OS versions
Win9x OS versions
开发工作环境的建立:
· Editplus
· UltraEdit32
MSDN
· Hexedit
Resource Wor5kshop
Soft-ICE
反汇编软件W32DASM
· Visual C++
破解工具介绍: http://www.e-works.net.cn/Articles/511/Article31815.htm
编译一个例子:
C:\Source\test\test>dir
驱动器 C 中的卷是 DISK-C
卷的序列号是 4089-CA39
C:\Source\test\test 的目录
2007-01-29 20:59 <DIR> .
2007-01-29 20:59 <DIR> ..
1998-02-15 21:49 766 Main.ico
2005-07-24 22:25 1,461 Test.asm
2002-01-29 22:01 20 Test.rc
3 个文件 2,247 字节
2 个目录 3,169,656,832 可用字节
C:\Source\test\test>ml /c /coff Test.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997. All rights reserved.
Assembling: Test.asm
C:\Source\test\test>rc Test.rc
C:\Source\test\test>link /subsystem:windows Test.obj test.res
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
C:\Source\test\test>dir test.exe
驱动器 C 中的卷是 DISK-C
卷的序列号是 4089-CA39
C:\Source\test\test 的目录
2007-01-29 20:59 3,072 Test.exe 基本开发环境基本安装完成~:)
[ Last edited by redtek on 2007-1-29 at 08:59 PM ]
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-1-30 02:44 |
|
|
zhengzhichu01
新手上路
积分 3
发帖 2
注册 2007-2-3
状态 离线
|
|
2007-2-9 02:25 |
|
|
redtek
金牌会员
积分 2902
发帖 1147
注册 2006-9-21
状态 离线
|
『第
120 楼』:
有好几次都想把书给撕了,要不就想砸点什么东东,……终于把入门的内容给看完了~:)
|
Redtek,一个永远在网上流浪的人……
_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._ |
|
2007-2-9 11:24 |
|
|