文档库 最新最全的文档下载
当前位置:文档库 › 汇编教程汇编语言编程实例

汇编教程汇编语言编程实例

汇编教程汇编语言编程实例
汇编教程汇编语言编程实例

汇编语言编程实例一这一章,我们要把我们已学的知识集合起来。具体来讲,我们来写一个使用ODBC APIs的程序.为简单起见,这个程序中我使用Microsoft的Access数据库(Microso ft Access 97) .

注意:如果你使用的windows.inc 是1.18及其以下版本,在开始编译之前要修改其中的一个小bug.在windows.inc中查找 "SQL_NULL_HANDLE",将得到下面这行:

SQL_NULL_HANDLE equ 0L

将0后面的"L"删除,象这样:

SQL_NULL_HANDLE equ 0

这个程序是一个基于对话框的程序,有一个简单的菜单.当用户选择"connect"时,它将试图连接test.mdb数据库,如果连接成功,将显示由ODBC驱动程序返回的完整连接字符串.接下来,用户可选择"View All Records"命令,程序会使用listview control来显示数据库中的所有数据.用户还可以选择"Query"命令来查询特定的记录.例子程序将会显示一个小对话框提示用户输入想找的人名.当用户按下OK钮或回车键,程序将执行一个查询来查找符合条件的记录.当用户完成对数据库的操作时,可以选择"disconnect"命令与数据库断开连接.

现在看一下源程序:

.386

.model flat,stdcall

include \masm32\include\windows.inc

include \masm32\include\kernel32.inc

include \masm32\include\odbc32.inc

include \masm32\include\comctl32.inc

include \masm32\include\user32.inc

includelib \masm32\lib\odbc32.lib

includelib \masm32\lib\comctl32.lib

includelib \masm32\lib\kernel32.lib

includelib \masm32\lib\user32.lib

IDD_MAINDLG equ 101

IDR_MAINMENU equ 102

IDC_DATALIST equ 1000

IDM_CONNECT equ 40001

IDM_DISCONNECT equ 40002

IDM_QUERY equ 40003

IDC_NAME equ 1000

IDC_OK equ 1001

IDC_CANCEL equ 1002

IDM_CUSTOMQUERY equ 40004

IDD_QUERYDLG equ 102

DlgProc proto hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

QueryProc proto hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD SwitchMenuState proto :DWORD

ODBCConnect proto :DWORD

ODBCDisconnect proto :DWORD

RunQuery proto :DWORD

.data?

hInstance dd ?

hEnv dd ?

hConn dd ?

hStmt dd ?

Conn db 256 dup(?)

StrLen dd ?

hMenu dd ? ; 主菜单句柄

hList dd ? ; listview control句柄

TheName db 26 dup(?)

TheSurname db 26 dup(?)

TelNo db 21 dup(?)

NameLength dd ?

SurnameLength dd ?

TelNoLength dd ?

SearchName db 26 dup(?)

ProgPath db 256 dup(?)

ConnectString db 1024 dup(?)

.data

SQLStatement db "select * from main",0

WhereStatement db " where name=?",0

strConnect db "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=",0 DBName db "test.mdb",0

ConnectCaption db "Complete Connection String",0

Disconnect db "Disconnect successful",0

AppName db "ODBC Test",0

AllocEnvFail db "Environment handle allocation failed",0 AllocConnFail db "Connection handle allocation failed",0 SetAttrFail db "Cannot set desired ODBC version",0

NoData db "You must type the name in the edit box",0

ExecuteFail db "Execution of SQL statement failed",0

ConnFail db "Connection attempt failed",0

AllocStmtFail db "Statement handle allocation failed",0

Heading1 db "Name",0

Heading2 db "Surname",0

Heading3 db "Telephone No.",0

.code

start:

invoke GetModuleHandle, NULL

mov hInstance,eax

call GetProgramPath

invoke DialogBoxParam, hInstance, IDD_MAINDLG,0,addr DlgProc,0

invoke ExitProcess,eax

invoke InitCommonControls

DlgProc proc hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

.if uMsg==WM_INITDIALOG

invoke GetMenu, hDlg

mov hMenu,eax

invoke GetDlgItem, hDlg, IDC_DATALIST

mov hList,eax

call InsertColumn

.elseif uMsg==WM_CLOSE

invoke GetMenuState, hMenu, IDM_CONNECT,MF_BYCOMMAND

.if eax==MF_GRAYED

invoke ODBCDisconnect, hDlg

.endif

invoke EndDialog,hDlg, 0

.elseif uMsg==WM_COMMAND

.if lParam==0

mov eax,wParam

.if ax==IDM_CONNECT

invoke ODBCConnect,hDlg

.elseif ax==IDM_DISCONNECT

invoke ODBCDisconnect,hDlg

.elseif ax==IDM_QUERY

invoke RunQuery,hDlg

.elseif ax==IDM_CUSTOMQUERY

invoke DialogBoxParam, hInstance, IDD_QUERYDLG,hDlg, addr QueryProc, 0 .endif

.endif

.else

mov eax,FALSE

ret

.endif

mov eax,TRUE

ret

DlgProc endp

GetProgramPath proc

invoke GetModuleFileName, NULL,addr ProgPath,sizeof ProgPath

std

mov edi,offset ProgPath

add edi,sizeof ProgPath-1

mov al,"\"

mov ecx,sizeof ProgPath

repne scasb

cld

mov byte ptr [edi+2],0

ret

GetProgramPath endp

SwitchMenuState proc Flag:DWORD

.if Flag==TRUE

invoke EnableMenuItem, hMenu, IDM_CONNECT, MF_GRAYED

invoke EnableMenuItem, hMenu, IDM_DISCONNECT, MF_ENABLED

invoke EnableMenuItem, hMenu, IDM_QUERY, MF_ENABLED

invoke EnableMenuItem, hMenu, IDM_CUSTOMQUERY, MF_ENABLED

.else

invoke EnableMenuItem, hMenu, IDM_CONNECT, MF_ENABLED

invoke EnableMenuItem, hMenu, IDM_DISCONNECT, MF_GRAYED

invoke EnableMenuItem, hMenu, IDM_QUERY, MF_GRAYED

invoke EnableMenuItem, hMenu, IDM_CUSTOMQUERY, MF_GRAYED

.endif

ret

SwitchMenuState endp

ODBCConnect proc hDlg:DWORD

invoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_NULL_HANDLE, addr hEnv

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

invoke SQLSetEnvAttr, hEnv,SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3,0

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

invoke SQLAllocHandle, SQL_HANDLE_DBC, hEnv, addr hConn

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

invoke lstrcpy,addr ConnectString,addr strConnect

invoke lstrcat,addr ConnectString, addr ProgPath

invoke lstrcat, addr ConnectString,addr DBName

invoke SQLDriverConnect, hConn, hDlg, addr ConnectString, sizeof ConnectString, addr Conn, sizeof Conn,addr StrLen, SQL_DRIVER_COMPLETE

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

invoke SwitchMenuState,TRUE

invoke MessageBox,hDlg, addr Conn,addr ConnectCaption,MB_OK+MB_ICONINFORMATION .else

invoke SQLFreeHandle, SQL_HANDLE_DBC, hConn

invoke SQLFreeHandle, SQL_HANDLE_ENV, hEnv

invoke MessageBox, hDlg, addr ConnFail, addr AppName, MB_OK+MB_ICONERROR

.endif

.else

invoke SQLFreeHandle, SQL_HANDLE_ENV, hEnv

invoke MessageBox, hDlg, addr AllocConnFail, addr AppName, MB_OK+MB_ICONERROR .endif

.else

invoke SQLFreeHandle, SQL_HANDLE_ENV, hEnv

invoke MessageBox, hDlg, addr SetAttrFail, addr AppName, MB_OK+MB_ICONERROR

.endif

.else

invoke MessageBox, hDlg, addr AllocEnvFail, addr AppName, MB_OK+MB_ICONERROR .endif

ret

ODBCConnect endp

ODBCDisconnect proc hDlg:DWORD

invoke SQLDisconnect, hConn

invoke SQLFreeHandle, SQL_HANDLE_DBC, hConn

invoke SQLFreeHandle, SQL_HANDLE_ENV, hEnv

invoke SwitchMenuState, FALSE

invoke ShowWindow,hList, SW_HIDE

invoke MessageBox,hDlg,addr Disconnect, addr AppName,MB_OK+MB_ICONINFORMATION ret

ODBCDisconnect endp

InsertColumn proc

LOCAL lvc:LV_COLUMN

mov lvc.imask,LVCF_TEXT+LVCF_WIDTH

mov lvc.pszText,offset Heading1

mov lvc.lx,150

invoke SendMessage,hList, LVM_INSERTCOLUMN,0,addr lvc

mov lvc.pszText,offset Heading2

invoke SendMessage,hList, LVM_INSERTCOLUMN, 1 ,addr lvc

mov lvc.pszText,offset Heading3

invoke SendMessage,hList, LVM_INSERTCOLUMN, 3 ,addr lvc

ret

InsertColumn endp

FillData proc

LOCAL lvi:LV_ITEM

LOCAL row:DWORD

invoke SQLBindCol, hStmt,1,SQL_C_CHAR, addr TheName, sizeof TheName,addr NameLe ngth

invoke SQLBindCol, hStmt,2,SQL_C_CHAR, addr TheSurname, sizeof TheSurname,addr SurnameLength

invoke SQLBindCol, hStmt,3,SQL_C_CHAR, addr TelNo, sizeof TelNo,addr TelNoLengt h

mov row,0

.while TRUE

mov byte ptr ds:[TheName],0

mov byte ptr ds:[TheSurname],0

mov byte ptr ds:[TelNo],0

invoke SQLFetch, hStmt

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

mov lvi.imask,LVIF_TEXT+LVIF_PARAM

push row

pop lvi.iItem

mov lvi.iSubItem,0

mov lvi.pszText, offset TheName

push row

pop lvi.lParam

invoke SendMessage,hList, LVM_INSERTITEM,0, addr lvi

mov lvi.imask,LVIF_TEXT

inc lvi.iSubItem

mov lvi.pszText,offset TheSurname

invoke SendMessage,hList,LVM_SETITEM, 0,addr lvi

inc lvi.iSubItem

mov lvi.pszText,offset TelNo

invoke SendMessage,hList,LVM_SETITEM, 0,addr lvi

inc row

.else

.break

.endif

.endw

ret

FillData endp

RunQuery proc hDlg:DWORD

invoke ShowWindow, hList, SW_SHOW

invoke SendMessage, hList, LVM_DELETEALLITEMS,0,0

invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

invoke SQLExecDirect, hStmt, addr SQLStatement, sizeof SQLStatement

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

invoke FillData

.else

invoke ShowWindow, hList, SW_HIDE

invoke MessageBox,hDlg,addr ExecuteFail, addr AppName, MB_OK+MB_ICONERROR .endif

invoke SQLCloseCursor, hStmt

invoke SQLFreeHandle, SQL_HANDLE_STMT, hStmt

.else

invoke ShowWindow, hList, SW_HIDE

invoke MessageBox,hDlg,addr AllocStmtFail, addr AppName, MB_OK+MB_ICONERROR .endif

ret

RunQuery endp

QueryProc proc hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

.if uMsg==WM_CLOSE

invoke SQLFreeHandle, SQL_HANDLE_STMT, hStmt

invoke EndDialog, hDlg,0

.elseif uMsg==WM_INITDIALOG

invoke ShowWindow, hList, SW_SHOW

invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

invoke lstrcpy, addr Conn, addr SQLStatement

invoke lstrcat, addr Conn, addr WhereStatement

invoke SQLBindParameter,hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,25,0, a ddr SearchName,25,addr StrLen

invoke SQLPrepare, hStmt, addr Conn, sizeof Conn

.else

invoke ShowWindow, hList, SW_HIDE

invoke MessageBox,hDlg,addr AllocStmtFail, addr AppName, MB_OK+MB_ICONERROR invoke EndDialog, hDlg,0

.endif

.elseif uMsg==WM_COMMAND

mov eax, wParam

shr eax,16

.if ax==BN_CLICKED

mov eax,wParam

.if ax==IDC_OK

invoke GetDlgItemText, hDlg, IDC_NAME, addr SearchName, 25

.if ax==0

invoke MessageBox, hDlg,addr NoData, addr AppName, MB_OK+MB_ICONERROR

invoke GetDlgItem, hDlg, IDC_NAME

invoke SetFocus, eax

.else

invoke lstrlen,addr SearchName

mov StrLen,eax

invoke SendMessage, hList, LVM_DELETEALLITEMS,0,0

invoke SQLExecute, hStmt

invoke FillData

invoke SQLCloseCursor, hStmt

.endif

.else

invoke SQLFreeHandle, SQL_HANDLE_STMT, hStmt

invoke EndDialog, hDlg,0

.endif

.endif

.else

mov eax,FALSE

ret

.endif

mov eax,TRUE

ret

QueryProc endp

end start

分析

start:

invoke GetModuleHandle, NULL

mov hInstance,eax

call GetProgramPath

当程序开始时,将获得实例句柄并获得所在路径.默认情况下数据库 test.mdb应与程序处于同一文件夹.

GetProgramPath proc

invoke GetModuleFileName, NULL,addr ProgPath,sizeof ProgPath

std

mov edi,offset ProgPath

add edi,sizeof ProgPath-1

mov al,"\"

mov ecx,sizeof ProgPath

repne scasb

cld

mov byte ptr [edi+2],0

ret

GetProgramPath endp

GetProgramPath调用GetModuleFileName来获得程序的全路径名.接着在路径中查找最后一个"\"符",通过将文件名的第一个字符置为0获得(truncate)" 文件名. 因此我们在Pr ogPath中获得了程序的路径名.

然后程序将用DialogBoxParam显示主对话框.当主对话框第一次被载入时,它将获得菜单句柄和listview control句柄.接下来在listview control中插入三列(因为我们已经知道结果集将包含三列.因为是我们先建的表.)

现在,它就等待用户的动作了.如果用户在菜单中选择"connect",将会调用ODBCConnec t函数.

ODBCConnect proc hDlg:DWORD

invoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_NULL_HANDLE, addr hEnv

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

它做的第一件事是调用SQLAllocHandle来分配一个环境句柄.

invoke SQLSetEnvAttr, hEnv,SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3,0

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

获得环境句柄后,程序调用SQLSetEnvAttr来表示将要使用ODBC 3.x的语法.

invoke SQLAllocHandle, SQL_HANDLE_DBC, hEnv, addr hConn

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

如果一切顺利,程序将通过调用SQLAllocHandle获得连接句柄来实现连接.

invoke lstrcpy,addr ConnectString,addr strConnect

invoke lstrcat,addr ConnectString, addr ProgPath

invoke lstrcat, addr ConnectString,addr DBName

接着填写连接字符串.完整的连接字符串将被用在ConnectionString

invoke SQLDriverConnect, hConn, hDlg, addr ConnectString, sizeof ConnectString, addr Conn, sizeof Conn,addr StrLen, SQL_DRIVER_COMPLETE

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

invoke SwitchMenuState,TRUE

invoke MessageBox,hDlg, addr Conn,addr ConnectCaption,MB_OK+MB_ICONINFORMATION

当连接字符串完成,程序将调用SQLDriverConnect来通过MS Access ODBC 驱动程序连接test.mdb数据库.如果文件test.mdb不存在,ODBC driver将提示用户输入该文件的位置,因为我们已经设定了SQL_DRIVER_COMPLETE标志.当SQLDriverConnect成功返回时, Conn 被填入由ODBC驱动程序创建的完整连接字符串.我们通过一个message box来将其显示给用户. SwitchMenuState是一个单纯切换菜单选项可用的函数.

现在,到数据库的连接已经建立并被打开,并一直保持打开状态直到用户选择关闭.

当用户选择了"View All Records"命令, 对话框过程将调用RunQuery.函数

RunQuery proc hDlg:DWORD

invoke ShowWindow, hList, SW_SHOW

invoke SendMessage, hList, LVM_DELETEALLITEMS,0,0

由于listview control在创建时是不可见的,现在我们把它显示出来.还有要把其中的所有元素(如果有的话)删掉.

invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

接下来,程序将获得一个语句句柄.

invoke SQLExecDirect, hStmt, addr SQLStatement, sizeof SQLStatement

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

通过 SQLExecDirect执行已准备好的SQL语句.我这里选择SQLExecDirect 的原因是只须执行一次.

invoke FillData

执行SQL语句后,将返回一个结果集.我们使用 FillData函数来从结果集中解出数据并将其放入listview control中.

FillData proc

LOCAL lvi:LV_ITEM

LOCAL row:DWORD

invoke SQLBindCol, hStmt,1,SQL_C_CHAR, addr TheName, sizeof TheName,addr NameLe ngth

invoke SQLBindCol, hStmt,2,SQL_C_CHAR, addr TheSurname, sizeof TheSurname,addr SurnameLength

invoke SQLBindCol, hStmt,3,SQL_C_CHAR, addr TelNo, sizeof TelNo,addr TelNoLengt h

现在,结果集被返回.我们要绑定结果集的所有三列到我们提供的缓冲区中.这是调用S QLBindCol来实现的.注意我们要对每一列分别调用.并且我们并不需要绑定所有的列:只要绑定要获得数据的列就行了.

mov row,0

.while TRUE

mov byte ptr ds:[TheName],0

mov byte ptr ds:[TheSurname],0

mov byte ptr ds:[TelNo],0

当列中没有数据时,我们初始化缓冲区为NULLs.更好的方法是用SQLBindCol指定的变量中数据的长度.在我们的例子中,我们可以检查NameLength, SurnameLength和TelNoLeng th中的值的确切长度.

invoke SQLFetch, hStmt

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

mov lvi.imask,LVIF_TEXT+LVIF_PARAM

push row

pop lvi.iItem

mov lvi.iSubItem,0

mov lvi.pszText, offset TheName

push row

pop lvi.lParam

invoke SendMessage,hList, LVM_INSERTITEM,0, addr lvi

其它都很简单了.调用SQLFetch 来获得结果集的一行,并将其存入listview control 的缓冲区中.当没有更多的行供检索时(已到达文件尾), SQLFetch返回SQL_NO_DATA并且程序跳出循环.

invoke SQLCloseCursor, hStmt

invoke SQLFreeHandle, SQL_HANDLE_STMT, hStmt

当完成对结果集的操作时,调用SQLCloseCursor关闭结果集并调用SQLFreeHandle释放语句句柄.

当用户选择"Query"命令,程序显示另一个对话框供用户输入要查询的名字.

.elseif uMsg==WM_INITDIALOG

invoke ShowWindow, hList, SW_SHOW

invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt

.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

invoke lstrcpy, addr Conn, addr SQLStatement

invoke lstrcat, addr Conn, addr WhereStatement

invoke SQLBindParameter,hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,25,0, a ddr SearchName,25,addr StrLen

invoke SQLPrepare, hStmt, addr Conn, sizeof Conn

对话框做的第一件事是显示listview control.接下来分配一个语句句柄以创建SQL语句.这个SQL语句有一个"where"子句及一个参数标志符"?". 完整的SQL语句是:

select * from main where name=?

接着程序调用SQLBindParameter 来建立参数标志符与缓冲区SearchName的连接,这样当SQL语句被执行时,ODBC驱动程序就可从SearchName中获得需要的字符串.接下来,程序调用SQLPrepare来编译SQL语句. 这样我们只要准备/编译SQL语句一次就可多次使用.因为SQL语句已被编译过,接下来的执行过程会快一些.

.if ax==IDC_OK

invoke GetDlgItemText, hDlg, IDC_NAME, addr SearchName, 25

.if ax==0

invoke MessageBox, hDlg,addr NoData, addr AppName, MB_OK+MB_ICONERROR

invoke GetDlgItem, hDlg, IDC_NAME

invoke SetFocus, eax

.else

当用户在编辑框(edit control)中填入了一些名字并按下回车键, 程序将获得编辑框中的文本并检查是否是空字符串.如果是,则显示一个message box并将键盘焦点设在编辑框上,提示用户输入名字.

invoke lstrlen,addr SearchName

mov StrLen,eax

invoke SendMessage, hList, LVM_DELETEALLITEMS,0,0

invoke SQLExecute, hStmt

invoke FillData

invoke SQLCloseCursor, hStmt

如果编辑框中已有字符串,程序会获得它的长度并将其放入StrLen中供ODBC驱动程序使用(记住我们已将StrLen的地址传送给了SQLBindParameter). 接下来程序使用获得的语句句柄调用SQLExecute执行已准备好的SQL语句.当 SQLExecute返回时,程序调用FillDa ta在listview control显示结果.因为我们不会再用到结果集,调用SQLCloseCursor来关闭它.

第三章 8086汇编语言程序格式

第三章8086汇编语言程序格式 练习题 3.4.1 单项选择题 1.下列选项中不能作为名字项的是()。 A.FH B.A3 C.3B D.FADC 2.下列指令不正确的是()。 A.MOV AL,123 B.MOV AL,123Q C.MOV AL,123D D.MOV AL,123H 3.下列指令不正确的是()。 A.MOV BL,OFFSET A B.LEA BX,A C.MOV BX,OFFSET A D.MOV BX,A 4.若定义“BUF DB 1,2,3,4”,执行MOV AL,TYPE BUF 后AL=()。 A.0 B.1 C.2 D.3 5.若定义“A EQU 100”,执行“MOV AX,A”后,AX=()。 A.A的偏移地址B.A单元中的内容 C.100 D.A的段地址 6.若定义“B DW 1,2,10 DUP(0)”,则该伪指令分配()字节单元。 A.10 B.20 C.22 D.24 7.若定义“C DD 2,4”,则该伪指令分配()个字节单元。 A.2 B.4 C.6 D.8 8、伪指令是()规定的汇编说明符,它在源程序汇编时进行说明。 A、DEBUG B、LINK C、MASM D、EDIT 9.在上机操作过程中,MASM命令执行后,除了生成一个目标文件外,根据选择还可以生成一个()文件。 A..LST B..EXE C..MAP D..ASM 10.LINK命令执行后可以生成一个以()为扩展名的文件。 A.ASM B.EXE C.OBJ D.COM 11.一个段最大可定义()字节。 A.1M B.64K C.32K D.16K 12.若要求一个段的起始位置能被256整除的单元开始,在定位方式选项中应选()。 A.BYTE B.WORD C.PARA D.PAGE 13.宏指令与子程序相比,在多次调用时,宏指令调用的目标程序长度比子程序调用的()。 A.相同B.长C.短D.不定 14.宏指令与子程序相比,子程序调用的执行速度比宏指令的()。 A.相同B.快C.慢D.不定 15.ASSUME伪指令说明了汇编程序所定义段与段寄存器的关系,它只影响()的设定。 A.源程序B.目标程序C.汇编程序D.连接程序

汇编语言 快速入门

“哎哟,哥们儿,还捣鼓汇编呢?那东西没用,兄弟用VB"钓"一个API就够你忙活个十天半月的,还不一定搞出来。”此君之言倒也不虚,那吾等还有无必要研他一究呢?(废话,当然有啦!要不然你写这篇文章干嘛。)别急,别急,让我把这个中原委慢慢道来:一、所有电脑语言写出的程序运行时在内存中都以机器码方式存储,机器码可以被比较准确的翻译成汇编语言,这是因为汇编语言兼容性最好,故几乎所有跟踪、调试工具(包括WIN95/98下)都是以汇编示人的,如果阁下对CRACK颇感兴趣……;二、汇编直接与硬件打交道,如果你想搞通程序在执行时在电脑中的来龙去脉,也就是搞清电脑每个组成部分究竟在干什么、究竟怎么干?一个真正的硬件发烧友,不懂这些可不行。三、如今玩DOS的多是“高手”,如能像吾一样混入(我不是高手)“高手”内部,不仅可以从“高手”朋友那儿套些黑客级“机密”,还可以自诩“高手”尽情享受强烈的虚荣感--#$%&“醒醒!” 对初学者而言,汇编的许多命令太复杂,往往学习很长时间也写不出一个漂漂亮亮的程序,以致妨碍了我们学习汇编的兴趣,不少人就此放弃。所以我个人看法学汇编,不一定要写程序,写程序确实不是汇编的强项,大家不妨玩玩DEBUG,有时CRACK出一个小软件比完成一个程序更有成就感(就像学电脑先玩游戏一样)。某些高深的指令事实上只对有经验的汇编程序员有用,对我们而言,太过高深了。为了使学习汇编语言有个好的开始,你必须要先排除那些华丽复杂的命令,将注意力集中在最重要的几个指令上(CMP LOOP MOV JNZ……)。但是想在啰里吧嗦的教科书中完成上述目标,谈何容易,所以本人整理了这篇超浓缩(用WINZIP、WINRAR…依次压迫,嘿嘿!)教程。大言不惭的说,看通本文,你完全可以“不经意”间在前辈或是后生卖弄一下DEBUG,很有成就感的,试试看!那么――这个接下来呢?――Here we go!(阅读时看不懂不要紧,下文必有分解) 因为汇编是通过CPU和内存跟硬件对话的,所以我们不得不先了解一下CPU和内存:(关于数的进制问题在此不提) CPU是可以执行电脑所有算术╱逻辑运算与基本I/O控制功能的一块芯片。一种汇编语言只能用于特定的CPU。也就是说,不同的CPU其汇编语言的指令语法亦不相同。个人电脑由1981年推出至今,其CPU发展过程为:8086→80286→80386→80486→PENTIUM →……,还有AMD、CYRIX等旁支。后面兼容前面CPU的功能,只不过多了些指令(如多能奔腾的MMX指令集)、增大了寄存器(如386的32位EAX)、增多了寄存器(如486的FS)。为确保汇编程序可以适用于各种机型,所以推荐使用8086汇编语言,其兼容性最佳。本文所提均为8086汇编语言。寄存器(Register)是CPU内部的元件,所以在寄存器之间的数据传送非常快。用途:1.可将寄存器内的数据执行算术及逻辑运算。2.存于寄存器内的地址可用来指向内存的某个位置,即寻址。3.可以用来读写数据到电脑的周边设备。8086有8个8位数据寄存器,这些8位寄存器可分别组成16位寄存器:AH&AL=AX:累加寄存器,常用于运算;BH&BL=BX:基址寄存器,常用于地址索引;CH&CL=CX:计数寄存器,常用于计数;DH&DL=DX:数据寄存器,常用于数据传递。为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:CS(Code Segment):代码段寄存器;DS(Data Segment):数据段寄存器;SS(Stack Segment):堆栈段寄存器;ES(Extra Segment):附加段寄存器。当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器CS,DS,SS来指向这些起始位置。通常是将DS固定,而根据需要修改CS。所以,程序可以在可寻址空间小于64K的情况下被写成任意大小。所以,程序和其数据组合起来的大小,限制在DS所指的64K内,这就是COM文件不得大于64K的原因。8086以内存做为战场,用寄存器做为军事基地,以加速工作。除了前面所提的寄存器外,还有一些特殊功能的寄存器:IP(Intruction Pointer):指

汇编语言知识大全

第一章基础知识: 一.机器码:1.计算机只认识0,1两种状态。而机器码只能由0,1组成。故机器码相当难认,故产生了汇编语言。 2.其中汇编由三类指令形成:汇编指令(有机器码对应),伪指令,其他符号(编译的时候有用)。 每一总CPU都有自己的指令集;注意学习的侧重点。 二.存储器:1.存储单元中数据和指令没任何差别。 2.存储单元:Eg:128个储存单元(0~127)128byte。 线: 1.地址总线:寻址用,参数(宽度)为N根,则可以寻到2^N个内存单元。 据总线:传送数据用,参数为N根,一次可以传送N/8个存储单元。 3.控制总线:cpu对元器件的控制能力。越多控制力越强。 四.内存地址空间:1.由地址总线决定大小。 2.主板:cpu和核心器件(或接口卡)用地址总线,数据总线,控制总 线连接起来。 3.接口卡:由于cpu不能直接控制外设,需通过接口卡间接控制。

4.各类存储器芯片:RAM,BIOS(主板,各芯片)的ROM,接卡槽的 RAM CPU在操控他们的时候,把他们都当作内存来对待,把他们总的看作一个由 若干个存储单元组成的逻辑存储器,即我们所说的内存地址空间。 自己的一点理解:CPU对内存的操作是一样的,但是在cpu,内存,芯片之间的硬件本身所牵扯的线是不同的。所以一些地址的功能是对应一些芯片的。 第二章寄存器 引入:CPU中含有运算器,寄存器,控制器(由内部总线连接)。而寄存器是可以用来指令读写的部件。8086有14个寄存器(都是16位,2个存储空间)。 一.通用寄存器(ax,bx,cx,dx),16位,可以分为高低位 注意1.范围:16位的2^16-1,8位的2^8-1 2.进行数据传送或运算时要注意位数对应,否则会报错 二.字:1. 1个字==2个字节。 2. 在寄存器中的存储:0x高位字节低位字节;单元认定的是低单元 数制,16进制h,2进制b

ARM经典汇编程序

1冒泡排序的ARM汇编程序ORG 09B0H QUE:MOV R3,#50H QUE1:MOV A,R3 MOV R0,A MOV R7,#0AH CLR 00H MOV A,@R0 Q12:INC R0 MOV R2,A CLR C MOV 22H,@R0 CJNE A,22H,Q13 SETB C Q13:MOV A,R2 JC Q11 SETB 00H XCH A,@R0 DEC R0 XCH A,@R0 INC R0 Q11:MOV A,@R0 DJNZ R7,Q12 JB 00H,QUE1 SJMP $ END

2 ARM汇编希尔排序法对10个带符号数进行排序Code: void shell(int src[],int l,int r){ int ih; r++; for(ih=1;ih<(r-l)/9;ih=ih*3+1); //eax,ih //ebx,il //ecx,ir //edx,cmps _asm{ push eax push ebx push ecx push edx push esi push edi;貌似这堆进栈用处不大哎 mov edi,src mov eax,dword ptr [ih] LIH: cmp eax,0 jna EXIH mov ebx,eax dec ebx LLH: cmp ebx,dword ptr [r] jnb EXLLH mov ecx,ebx mov edx,dword ptr [edi+ecx*4]

LCMP: mov esi,eax dec esi cmp ecx,esi jna EXCMP push ecx sub ecx,eax cmp edx,dword ptr [edi+ecx*4] pop ecx jnb EXCMP push ebx push ecx sub ecx,eax mov ebx,dword ptr [edi+ecx*4] pop ecx mov dword ptr [edi+ecx*4],ebx pop ebx sub ecx,eax jmp LCMP EXCMP: mov dword ptr [edi+ecx*4],edx inc ebx jmp LLH EXLLH: push ecx mov ecx,3 push edx cdq

6、汇编学习从入门到精通(荐书)

汇编学习从入门到精通Step By Step 2007年12月15日星期六00:34 信息来源:https://www.wendangku.net/doc/558945832.html,/hkbyest/archive/2007/07/22/1702065.aspx Cracker,一个充满诱惑的词。别误会,我这里说的是软件破解,想做骇客的一边去,这年头没人说骇客,都是“黑客”了,嘎嘎~ 公元1999年的炎热夏季,我捧起我哥留在家的清华黄皮本《IBM-PC汇编语言程序设计》,苦读。一个星期后我那脆弱的小心灵如玻璃般碎裂了,为了弥补伤痛我哭爹求妈弄了8k大洋配了台当时算是主流的PC,要知道那是64M内存!8.4G硬盘啊!还有传说中的Celeon 300A CPU。不过很可惜的是在当时那32k小猫当道的时代,没有宽带网络,没有软件,没有资料,没有论坛,理所当然我对伟大的计算机科学体系的第一步探索就此夭折,此时陪伴我的是那些盗版光盘中的游戏,把CRACK_XXX文件从光盘复制到硬盘成了时常的工作,偶尔看到光盘中的nfo 文件,心里也闪过一丝对破解的憧憬。 上了大学后有网可用了,慢慢地接触到了一些黑客入侵的知识,想当黑客是每一个充满好奇的小青年的神圣愿望,整天看这看那,偷偷改了下别人的网页就欢喜得好像第一次偷到鸡的黄鼠狼。 大一开设的汇编教材就是那不知版了多少次的《IBM-PC汇编语言程序设计》,凭着之前的那星期苦读,考试混了个80分。可惜当时头脑发热,大学60分万岁思想无疑更为主流,现在想想真是可惜了宝贵的学习时间。 不知不觉快毕业了,这时手头上的《黑客防线》,《黑客X档案》积了一大摞,整天注来注去的也厌烦了,校园网上的肉鸡一打一打更不知道拿来干什么。这时兴趣自然转向了crack,看着杂志上天书般的汇编代码,望望手头还算崭新的汇编课本,叹了口气,重新学那已经忘光了的汇编语言吧。咬牙再咬牙,看完寻址方式那章后我还是认输,不认不行啊,头快裂了,第三次努力终告失败。虽然此时也可以爆破一些简单的软件,虽然也知道搞破解不需要很多的汇编知识,但我还是固执地希望能学好这门基础中的基础课程。 毕业了,进入社会了,找工作,上班,换工作成了主流旋律,每天精疲力尽的哪有时间呢?在最初的中国移动到考公务员再到深圳再到家里希望的金融机构,一系列的曲折失败等待耗光了我的热情,我失业了,赋闲在家无所事事,唯一陪伴我的是那些杂志,课本,以及过时的第二台电脑。我不想工作,我对找工作有一种恐惧,我靠酒精麻醉自己,颓废一段日子后也觉得生活太过无聊了,努力看书考了个CCNA想出去,结果还是被现实的就业环境所打败。三年时间,一无所获。 再之后来到女朋友处陪伴她度过刚毕业踏入社会工作的适应时期,这段时间随便找了个电脑技术工作,每月赚那么个几百块做生活费。不过这半年让我收获比较大的就是时间充裕,接触到了不少新东西,我下定决心要把汇编学好,这时我在网上看到了别人推荐的王爽《汇编语言》,没抱什么希望在当当网购了人生中的第一次物,19块6毛,我记得很清楚,呵呵。 废话终于完了,感谢各位能看到这里,下面进入正题吧。

Windows X86-64位汇编语言入门

Windows X86-64位汇编语言入门 Windows X64汇编入门(1) 最近断断续续接触了些64位汇编的知识,这里小结一下,一是阶段学习的回顾,二是希望对64位汇编新手有所帮助。我也是刚接触这方面知识,文中肯定有错误之处,大家多指正。 文章的标题包含了本文的四方面主要内容: (1)Windows:本文是在windows环境下的汇编程序设计,调试环境为Windows Vista 64位版,调用的均为windows API。 (2)X64:本文讨论的是x64汇编,这里的x64表示AMD64和Intel的EM64T,而不包括IA64。至于三者间的区别,可自行搜索。 (3)汇编:顾名思义,本文讨论的编程语言是汇编,其它高级语言的64位编程均不属于讨论范畴。 (4)入门:既是入门,便不会很全。其一,文中有很多知识仅仅点到为止,更深入的学习留待日后努力。其二,便于类似我这样刚接触x64汇编的新手入门。 本文所有代码的调试环境:Windows Vista x64,Intel Core 2 Duo。 1. 建立开发环境 1.1 编译器的选择 对应于不同的x64汇编工具,开发环境也有所不同。最普遍的要算微软的MASM,在x64环境中,相应的编译器已经更名为ml64.exe,随Visual Studio 2005一起发布。因此,如果你是微软的忠实fans,直接安装VS2005既可。运行时,只需打开相应的64位命令行窗口(图1),便可以用ml64进行编译了。

第二个推荐的编译器是GoASM,共包含三个文件:GoASM编译器、GoLINK链接器和GoRC 资源编译器,且自带了Include目录。它的最大好外是小,不用为了学习64位汇编安装几个G 的VS。因此,本文的代码就在GoASM下编译。 第三个Yasm,因为不熟,所以不再赘述,感兴趣的朋友自行测试吧。 不同的编译器,语法会有一定差别,这在下面再说。 1.2 IDE的选择 搜遍了Internet也没有找到支持asm64的IDE,甚至连个Editor都没有。因此,最简单的方法是自行修改EditPlus的masm语法文件,这也是我采用的方法,至少可以得到语法高亮。当然,如果你懒得动手,那就用notepad吧。 没有IDE,每次编译时都要手动输入不少参数和选项,做个批处理就行了。 1.3 硬件与操作系统 硬件要求就是64位的CPU。操作系统也必须是64位的,如果在64位的CPU上安装了

汇编语言入门

汇编语言入门教程 对初学者而言,汇编的许多命令太复杂,往往学习很长时间也写不出一个漂漂亮亮的程序,以致妨碍了我们学习汇编的兴趣,不少人就此放弃。所以我个人看法学汇编,不一定要写程序,写程序确实不是汇编的强项,大家不妨玩玩DEBUG,有时CRACK出一个小软件比完成一个程序更有成就感(就像学电脑先玩游戏一样)。某些高深的指令事实上只对有经验的汇编程序员有用,对我们而言,太过高深了。为了使学习汇编语言有个好的开始,你必须要先排除那些华丽复杂的命令,将注意力集中在最重要的几个指令上(CMP LOOP MOV JNZ……)。但是想在啰里吧嗦的教科书中完成上述目标,谈何容易,所以本人整理了这篇超浓缩(用WINZIP、WINRAR…依次压迫,嘿嘿!)教程。大言不惭的说,看通本文,你完全可以“不经意”间在前辈或是后生卖弄一下DEBUG,很有成就感的,试试看!那么――这个接下来呢?――Here we go!(阅读时看不懂不要紧,下文必有分解) 因为汇编是通过CPU和内存跟硬件对话的,所以我们不得不先了解一下CPU和内存:(关于数的进制问题在此不提) CPU是可以执行电脑所有算术╱逻辑运算与基本I/O 控制功能的一块芯片。一种汇编语言只能用于特定的CPU。也就是说,不同的CPU其汇编语言的指令语法亦不相同。个人电脑由1981年推出至今,其CPU发展过程为:8086→80286→80386→80486→PENTIUM →……,还有AMD、CYRIX等旁支。后面兼容前面CPU的功能,只不过多了些指令(如多能奔腾的MMX指令集)、增大了寄存器(如386的32位EAX)、增多了寄存器(如486的FS)。为确保汇编程序可以适用于各种机型,所以推荐使用8086汇编语言,其兼容性最佳。本文所提均为8086汇编语言。寄存器(Register)是CPU内部的元件,所以在寄存器之间的数据传送非常快。用途:1.可将寄存器内的数据执行算术及逻辑运算。2.存于寄存器内的地址可用来指向内存的某个位置,即寻址。3.可以用来读写数据到电脑的周边设备。8086 有8个8位数据寄存器,这些8位寄存器可分别组成16位寄存器:AH&AL=AX:累加寄存器,常用于运算;BH&BL=BX:基址寄存器,常用于地址索引;CH&CL=CX:计数寄存器,常用于计数;DH&DL=DX:数据寄存器,常用于数据传递。为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:CS(Code Segment):代码段寄存器;DS(Data Segment):数据段寄存器;SS(Stack Segment):堆栈段寄存器;ES(Extra Segment):附加段寄存器。当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器CS,DS,SS 来指向这些起始位置。通常是将DS固定,而根据需要修改CS。所以,程序可以在可寻址空间小于64K的情况下被写成任意大小。所以,程序和其数据组合起来的大小,限制在DS 所指的64K内,这就是COM文件不得大于64K的原因。8086以内存做为战场,用寄存器做为军事基地,以加速工作。除了前面所提的寄存器外,还有一些特殊功能的寄存器:IP(Intruction Pointer):指令指针寄存器,与CS配合使用,可跟踪程序的执行过程;SP(Stack Pointer):堆栈指针,与SS配合使用,可指向目前的堆栈位置。BP(Base Pointer):基址指针寄存器,可用作SS 的一个相对基址位置;SI(Source Index):源变址寄存器可用来存放相对于DS段之源变址指针;DI(Destination Index):目的变址寄存器,可用来存放相对于ES 段之目的变址指针。还有一个标志寄存器FR(Flag Register),有九个有意义的标志,将在下文用到时详细说明。 内存是电脑运作中的关键部分,也是电脑在工作中储存信息的地方。内存组织有许多可存放

汇编语言-王爽-完美高清版视频教程

汇编语言》-王爽-完美高清版-零基础汇编语言入门书籍PDF格式 同时按ctrl+要下载的地址既可下载对应的视频 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f61cb107c8 001第一章- 基础知识01 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6806f45b8 002第一章- 基础知识02 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6ec42d4d3 003第一章- 基础知识03 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6deb05ec4 004第一章-基础知识04 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6e51f6838 005第一章- 基础知识05 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f66edaf8d3 006第二章- 寄存器(CPU工作原理)01 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6d07e07b9 007第二章- 寄存器(CPU工作原理)02 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6d7f585a8 008第二章- 寄存器(CPU工作原理)03 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f639d8b3cf 009第二章- 寄存器(CPU工作原理)04 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6dcadbde6 010第二章- 寄存器(CPU工作原理)05 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6ea3f01c1 011第二章- 寄存器(CPU工作原理)06 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f65b96a06f 012第二章- 寄存器(CPU工作原理)07 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f682da085a 013第三章- 寄存器(内存访问)01 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6486e698 014第三章- 寄存器(内存访问)02 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6b7491d9f 015第三章- 寄存器(内存访问)03 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f622b7f9a7 016第三章- 寄存器(内存访问)04 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f64e2424b9 017第三章- 寄存器(内存访问)05 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6e5132d4d 018第三章- 寄存器(内存访问)06 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f655c10e86 019第三章- 寄存器(内存访问)07 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6b22e64e6 020第四章- 第一个程序01 下载地址:https://www.wendangku.net/doc/558945832.html,/file/f6812126a4

最经典的51单片机经典流水灯汇编程序

单片机流水灯汇编程序设计 开发板上的8只LED为共阳极连接,即单片机输出端为低电平时即可点亮LED。 程序A: ;用最直接的方式实现流水灯 ORG 0000H START:MOV P1,#01111111B ;最下面的LED点亮 LCALL DELAY;延时1秒 MOV P1,#10111111B ;最下面第二个的LED点亮 LCALL DELAY;延时1秒 MOV P1,#11011111B ;最下面第三个的LED点亮(以下省略) LCALL DELAY MOV P1,#11101111B LCALL DELAY MOV P1,#11110111B LCALL DELAY MOV P1,#11111011B LCALL DELAY MOV P1,#11111101B LCALL DELAY MOV P1,#11111110B LCALL DELAY MOV P1,#11111111B ;完成第一次循环点亮,延时约0.25秒 AJMP START ;反复循环 ;延时子程序,12M晶振延时约250毫秒 DELAY: MOV R4,#2 L3: MOV R2 ,#250 L1: MOV R3 ,#250 L2: DJNZ R3 ,L2 DJNZ R2 ,L1 DJNZ R4 ,L3 RET END 程序B: ;用移位方式实现流水灯

ajmp main ;跳转到主程序 org 0030h ;主程序起始地址 main: mov a,#0feh ;给A赋值成11111110 loop: mov p1,a ;将A送到P1口,发光二极管低电平点亮 lcall delay ;调用延时子程序 rl a ;累加器A循环左移一位 ajmp loop ;重新送P1显示 delay: mov r3,#20 ;最外层循环二十次 d1: mov r4,#80 ;次外层循环八十次 d2: mov r5,#250 ;最内层循环250次 djnz r5,$ ;总共延时2us*250*80*20=0.8S djnz r4,d2 djnz r3,d1 ret end 51单片机经典流水灯程序,在51单片机的P2口接上8个发光二极管,产生流水灯的移动效果。 ORG 0 ;程序从0地址开始 START: MOV A,#0FEH ;让ACC的内容为11111110 LOOP: MOV P2,A ;让P2口输出ACC的内容 RR A ;让ACC的内容左移 CALL DELAY ;调用延时子程序 LJMP LOOP ;跳到LOOP处执行 ;0.1秒延时子程序(12MHz晶振)=================== DELAY: MOV R7,#200 ;R7寄存器加载200次数 D1: MOV R6,#250 ;R6寄存器加载250次数 DJNZ R6,$ ;本行执行R6次 DJNZ R7,D1 ;D1循环执行R7次 RET ;返回主程序

汇编语言基础知识

汇编语言基础知识 汇编语言是直接在硬件之上工作的编程语言,首先要了解硬件系统的结构,才能有 效地应用汇编语言对其编程,因此,本章对硬件系统结构的问题进行部分探讨,首先介绍了计算机的基本结构、Intel 公司微处理器的发展、计算机的语言以及汇编语言的特点,在此基础上重点介绍寄存器、内存组织等汇编语言所涉及到的基本知识。 1.1 微型计算机概述 微型计算机由中央处理器(Central Processing Unit ,CPU )、存储器、输入输出接口电路和总线构成。CPU 如同微型计算机的心脏,它的性能决定了整个微型计算机的各项关键指标。存储器包括随机存储器(Random Access Memory ,RAM )和只读存储器(Read Only Memory ,ROM )。输入输出接口电路用来连接外部设备和微型计算机。总线为CPU 和其他部件之间提供数据、地址和控制信息的传输通道。如图1.1所示为微型计算机的基本结构。 外部设备存储器输入输出接口电路中央处理器 CPU 地址总线 数据总线 控制总线 图1.1 微型计算机基本结构 特别要提到的是微型计算机的总线结构,它使系统中各功能部件之间的相互关系变 为各个部件面向总线的单一关系。一个部件只要符合总线结构标准, 就可以连接到采用这种总线结构的系统中,使系统功能得到扩展。 数据总线用来在CPU 与内存或其他部件之间进行数据传送。它是双向的,数据总线 的位宽决定了CPU 和外界的数据传送速度,8位数据总线一次可传送一个8位二进制数据(即一个字节),16位数据总线一次可传送两个字节。在微型计算机中,数据的含义是广义的,数据总线上传送的不一定是真正的数据,而可能是指令代码、状态量或控制量。 地址总线专门用来传送地址信息,它是单向的,地址总线的位数决定了 CPU 可以直接寻址的内存范围。如 CPU 的地址总线的宽度为N ,则CPU 最多可以寻找2N 个内存单 元。

单片机汇编语言经典一百例

51单片机实用程序库 4.1 流水灯 程序介绍:利用P1 口通过一定延时轮流产生低电平 输出,以达到发光二极管轮流亮的效果。实际应用中例如:广告灯箱彩灯、霓虹灯闪烁。 程序实例(LAMP.ASM) ORG 0000H AJMP MAIN ORG 0030H MAIN: 9 MOV A,#00H MOV P1,A ;灭所有的灯 MOV A,#11111110B MAIN1: MOV P1,A ;开最左边的灯 ACALL DELAY ;延时 RL A ;将开的灯向右边移 AJMP MAIN ;循环 DELAY:

MOV 30H,#0FFH D1: MOV 31H,#0FFH D2: DJNZ 31H,D2 DJNZ 30H,D1 RET END 4.2 方波输出 程序介绍:P1.0 口输出高电平,延时后再输出低电 平,循环输出产生方波。实际应用中例如:波形发生器。 程序实例(FAN.ASM): ORG 0000H MAIN: ;直接利用P1.0口产生高低电平地形成方波////////////// ACALL DELAY SETB P1.0 ACALL DELAY 10 CLR P1.0 AJMP MAIN ;////////////////////////////////////////////////// DELAY: MOV R1,#0FFH

DJNZ R1,$ RET END 五、定时器功能实例 5.1 定时1秒报警 程序介绍:定时器1每隔1秒钟将p1.o的输出状态改变1 次,以达到定时报警的目的。实际应用例如:定时报警器。程序实例(DIN1.ASM): ORG 0000H AJMP MAIN ORG 000BH AJMP DIN0 ;定时器0入口 MAIN: TFLA G EQU 34H ;时间秒标志,判是否到50个 0.2秒,即50*0.2=1秒 MOV TMOD,#00000001B;定时器0工作于方式 1 MOV TL0,#0AFH MOV TH0,#3CH ;设定时时间为0.05秒,定时 20次则一秒 11 SETB EA ;开总中断

汇编语言入门教程

汇编语言入门教程 2007-04-29 22:04对初学者而言,汇编的许多命令太复杂,往往学习很长时间也写不出一个漂漂亮亮的程序,以致妨碍了我们学习汇编的兴趣,不少人就此放弃。所以我个人看法学汇编,不一定要写程序,写程序确实不是汇编的强项,大家不妨玩玩DEBUG,有时CRACK 出一个小软件比完成一个程序更有成就感(就像学电脑先玩游戏一样)。某些高深的指令事实上只对有经验的汇编程序员有用,对我们而言,太过高深了。为了使学习汇编语言有个好的开始,你必须要先排除那些华丽复杂的命令,将注意力集中在最重要的几个指令上(CMP LOOP MOV JNZ……)。但是想在啰里吧嗦的教科书中完成上述目标,谈何容易,所以本人整理了这篇超浓缩(用WINZIP、WINRAR…依次压迫,嘿嘿!)教程。大言不惭的说,看通本文,你完全可以“不经意”间在前辈或是后生卖弄一下DEBUG,很有成就感的,试试看!那么――这个接下来呢?――Here we go!(阅读时看不懂不要紧,下文必有分解) 因为汇编是通过CPU和内存跟硬件对话的,所以我们不得不先了解一下CPU和内存:(关于数的进制问题在此不提) CPU是可以执行电脑所有算术╱逻辑运算与基本I/O 控制功能的一块芯片。一种汇编语言只能用于特定的CPU。也就是说,不同的CPU其汇编语言的指令语法亦不相同。个人电脑由1981年推出至今,其CPU发展过程为:8086→80286→80386→80486→PENTIUM →……,还有AMD、CYRIX等旁支。后面兼容前面CPU的功能,只不过多了些指令(如多能奔腾的MMX指令集)、增大了寄存器(如386的32位EAX)、增多了寄存器(如486的FS)。为确保汇编程序可以适用于各种机型,所以推荐使用8086汇编语言,其兼容性最佳。本文所提均为8086汇编语言。寄存器(Register)是CPU内部的元件,所以在寄存器之间的数据传送非常快。用途:1.可将寄存器内的数据执行算术及逻辑运算。2.存于寄存器内的地址可用来指向内存的某个位置,即寻址。3.可以用来读写数据到电脑的周边设备。8086 有8个8位数据寄存器,这些8位寄存器可分别组成16位寄存器:AH&AL=AX:累加寄存器,常用于运算;BH&BL=BX:基址寄存器,常用于地址索引;CH&CL=CX:计数寄存器,常用于计数;DH&DL=DX:数据寄存器,常用于数据传递。为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:CS(Code Segment):代码段寄存器;DS(Data Segment):数据段寄存器;SS(Stack Segment):堆栈段寄存器;ES(Extra Segment):附加段寄存器。当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器CS,DS,SS 来指向这些起始位置。通常是将DS固定,而根据需要修改CS。所以,程序可以在可寻址空间小于64K的情况下被写成任意大小。所以,程序和其数据组合起来的大小,限制在DS 所指的64K内,这就是COM文件不得大于64K的原因。8086以内存做为战场,用寄存器做为军事基地,以加速工作。除了前面所提的寄存器外,还有一些特殊功能的寄存器:IP(Intruction Pointer):指令指针寄存器,与CS配合使用,可跟踪程序的执行过程;SP(Stack Pointer):堆栈指针,与SS配合使用,可指向目前的堆栈位置。BP(Base Pointer):基址指针寄存器,可用作SS的一个相对基址位置;SI(Source Index):源变址寄存器可用来存放相对于DS 段之源变址指针;DI(Destination Index):目的变址寄存器,可用来存放相对于ES 段之目的变址指针。还有一个标志寄存器FR(Flag Register),有九个有意义的标志,将在下文用到时详细说明。

汇编经典代码

1.顺序程序设计 将两个多位十进制数相加,要求被加数、加数均以ASCⅡ码形式各自顺序存放在以DATA1和DATA2为首的五个内存单元中(低位在前),结果送回DATA1处。 DATA SEGMENT DATA1 DB 34H,35H,39H,38H,36H,' ' ;被加数 DATA2 DB 37H,34H,33H,36H,32H,' ' ;加数 DATA ENDS CODE SEGMENT MAIN PROC FAR ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX LEA SI,DATA1 ;有效地址送SI,为调用显示子程序做准备 CALL DISPLAY ;调用显示子程序 CALL CRLF ;调用回车换行子程序 LEA SI,DATA2 ;有效地址送SI,为调用显示子程序做准备,同时为加法运算做准备 CALL DISPLAY ;调用显示子程序 CALL CRLF ;调用回车换行子程序 LEA DI,DATA1 ;有效抵制送DI,为加法运算做准备 MOV AX,0 MOV BX,0 MOV CL,05H ;记录循环次数 ADDS: MOV AL,[SI] ;将加数送往AL SUB AL,30H ADD AL,BL ;加上进位 MOV BL,[DI] ;将被加数送往BL SUB BL,30H ADD AL,BL ;加法运算 ADD AL,30H CMP AL,3AH JA SUBA ;结果>=10,跳到SUBA JB NSUBA SUBA: SUB AL,0AH ;减去10的值,并置BL为1 MOV BL,01H JMP CONTINUE NSUBA: MOV BL,00H ;置BL为0 CONTINUE:MOV [DI],AL ;将相加的结果从AL送往DI的地址,即DATA1的地址INC DI ;地址加1 INC SI ;地址加1 LOOP ADDS ;循环 JC SHUCHU JNC SHUCHU2 SHUCHU2: MOV AL,31H ;CF为1设置结果最高位为1 JMP CONTINUE2 SHUCHU:MOV AL,30H ;CF为0设置结果最高位为0

汇编语言的编程步骤与调试方法

汇编语言的编程步骤与调试方法 一、汇编源程序的建立 1. 使用工具 (1)EDIT,记事本等文本编辑软件,编辑源程序,保存为.asm文 件; (2)ASM,MASM汇编程序,对源程序进行汇编,生成.obj文件- 目标文件,以及调试用.LST-列表文件和.CRF-交叉引用表; (3)Link连接程序,对使用的目标文件和库文件进行连接,生 成.exe文件,同时调试用.map-地址映像文件; 如果源程序无语法错误,上述三步将生成可运行的.exe文件, 如果运行结果无误,则完成对汇编程序的编程,如果运行后结果存 在错误,需要进行调试。 (4)Debug调试程序,对.exe文件进行调试,修改,直到程序正 确。 图3 目标程序生成步骤图2. 编程过程 (1)用文本编辑软件,编写扩展名为.asm的源文程序文件。 (2)用汇编程序对编好的源文件进行汇编。 命令行:masm [*.asm] ↙ 如果源文件中存在语法错误,则汇编程序将指出错误类型及位置,可根据这些信息重新编辑源文件,直至无语法错误,汇编后,将生成指定名称的目标文件.obj。 使用MASM50汇编程序进行汇编,输入命令行masm或者masm *.asm后,根据提示,输入文件名,在汇编没有错误的情况下,如屏幕所示:汇编程序可生成三个文件,*.obj,*.lst和*.crf。 *.obj-目标文件,用于连接生成可执行文件; *.lst-列表文件(可选),汇编语言汇编的机器语言与汇编语言对照表,可用于

调试; *.crf-交叉引用文件(可选),给出了用户定义的所有符号和对每个符号定义、引用的行号。 (3)目标文件的连接 命令行:link [*.obj] [*.obj] [*.lib] ↙ 连接程序,将多个目标程序及库文件,连接生成可执行的*.exe文件,同时可选择生成*.map文件。 *.map-地址映像文件,给出内存地址分配的有关信息。 下图所示屏幕,为Link连接两个目标文件,没有错误的情况下,生成*.exe 文件。 (4)执行程序 执行*.exe文件,观察程序运行结果,如果存在错误,需要进行调试。调试工具DEBUG是针对汇编语言程序设计的一种调试工具,熟练使用DEBUG有助于汇编语言程序员对于逻辑错误的调试。 二、汇编程序的调试

单片机汇编语言经典一百例

51单片机实用程序库 流水灯 程序介绍:利用P1 口通过一定延时轮流产生低电平 输出,以达到发光二极管轮流亮的效果。实际应用中例如:广告灯箱彩灯、霓虹灯闪烁。 程序实例() ORG 0000H AJMP MAIN ORG 0030H MAIN: 9 MOV A,#00H MOV P1,A ;灭所有的灯 MOV A,#B

MAIN1: MOV P1,A ;开最左边的灯 ACALL DELAY ;延时 RL A ;将开的灯向右边移 AJMP MAIN ;循环 DELAY: MOV 30H,#0FFH D1: MOV 31H,#0FFH D2: DJNZ 31H,D2 DJNZ 30H,D1 RET END 方波输出 程序介绍:口输出高电平,延时后再输出低电 平,循环输出产生方波。实际应用中例如:波形发生器。

程序实例(): ORG 0000H MAIN: ;直接利用口产生高低电平地形成方波步移位 ;显示个,十,百,千算机的内部计算都是二进 制,而二进制每除一个2,实际上是向右移一次。所以为了计算方便,我们选择取6个数,最后在算除法的时候,只需要用单片机自带的右移位命令移2次就行了。 27 十六进制六位数加法(数码显示) 程序实例: ORG 0000H MAIN: ADNUMBER EQU 30H ;AD转换值 ADDNUMBER EQU 31H ;加数值1

ADL EQU 32H ;// ADH EQU 33H ;ADL转换高低位值 DISL EQU 34H ;// DISH EQU 35H ;显示高低位值 ADDTOTAL EQU 36H ;第一次AD转换值ADDJW EQU 37H ;加法进位数 ADDHOLD EQU 38H ADDFLAG EQU 39H ;加标志 ENDFLAG EQU 40H ;赋初值//////////////////////////////////////////// MOV ADDHOLD,#00H MOV ADDNUMBER,#00H MOV ADL,#00H MOV ADH,#00H MOV DISL,#00H

汇编语言程序设计复习

知识点 第一章基础知识 (1)正负数的补码表示, 掌握计算机中数和字符的表示; eg.假设机器字长为8位,[+3]补=00000011B,[-3]补= 11111101 H 。 十六进制数0FFF8H表示的十进制正数为65528D,表示的十进制负数为-8D。 8位二进制数被看成是带符号补码整数时,其最小值是-128,最大值是 127 。 第二章80x86计算机组织 (1)中央处理机CPU的组成和80x86寄存器组,重点:专用寄存器,段寄存器 eg: IP寄存器中保存的是?代码段中的偏移地址FLAGS标志寄存器中共有几位条件状态位6位,有几位控制状态位2位,标志寄存器分为哪2类?陷阱标志,中断标志。 (2)存储单元的地址和内容每一个字节单元给以一个唯一的存储器地址,称为物理地址;一个存储单元中存放的信息称为该存储单元的内容。存储器地址的分段,(低位字节存放)低地址,(高位字节存放)高地址;实模式下逻辑地址、选择器和偏移地址;物理地址的表示段基地址加上偏移地址。 eg.如果SS=6000H,说明堆栈段起始物理地址是_____60000H___。 已知字节(00018H)=14H,字节(00017H)=20H,则字(00017H)为__1420H______。 如果(SI)=0088H,(DS)=5570H,对于物理地址为55788H的内存字单元,其内容为0235H,对于物理地址为5578AH的内存字单元,其内容为0E60H,那么执行指令LDS SI,[SI]以后,(SI)= 0235H ,(DS)= 0E60H . 第三章80x86的指令系统和寻址方式 与数据有关的寻址方式(立即寻址方式,寄存器寻址方式,直接寻址方式,寄存器间接寻址方式,寄存器相对寻址方式,基址变址寻址方式,相对基址变址寻址方式)和与转移地址有关的寻址方式(段内直接寻址,段内间接寻址,段间直接寻址,段间间接寻址)。数据传送指令(通用数据传送指令、累加器专用传送指令、输入输出指令)、算术指令(加法指令、减法指令(*加减指令对4个标志位的影响[of,cf,sf,zf])、乘法指令(*乘法指令的要求:目的操作数必须是累加器)、除法指令(*被除数在累加器中,除法指令执行完以后,商和余数在?))、逻辑指令(逻辑运算指令(*XOR,AND,OR,TEST指令及指令执行后对标志位的影响)、移位指令)、串处理指令(与REP相配合工作的MOVS、STOS、LODS 指令,与REPE/REPZ和REPNE/REPNZ联合工作的CMPS、SCAS指令)、控制转移指令(无条件转移指令、条件转移指令、循环指令、子程序调用指令、中断)。eg.【习题3.8】假定(DS)=2000H,(ES)=2100H,(SS)=1500H,(SI)=00A0H,

相关文档
相关文档 最新文档