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

合集下载

汇编语言除法程序编写

汇编语言除法程序编写

汇编语言除法程序编写汇编语言是一种底层的计算机语言,它直接操作计算机的硬件资源。

在汇编语言中,除法是一个重要的运算操作,它可以实现两个数的除法运算并得到商和余数。

本文将介绍如何编写一个汇编语言的除法程序。

首先,我们需要了解汇编语言中的除法指令。

在x86架构的汇编语言中,除法指令有两种形式:一种是无符号除法指令div,另一种是有符号除法指令idiv。

无符号除法指令div用于无符号整数的除法运算,有符号除法指令idiv用于有符号整数的除法运算。

接下来,我们来编写一个汇编语言的除法程序。

假设我们要计算两个无符号整数a和b的除法运算,我们可以按照以下步骤进行:1. 将被除数a存储在寄存器ax中,将除数b存储在寄存器bx中。

2. 使用div指令进行除法运算,将商存储在寄存器ax中,余数存储在寄存器dx中。

3. 将商和余数分别存储在内存中的指定位置。

下面是一个示例的汇编语言除法程序:```section .datadividend dw 10 ; 被除数divisor dw 3 ; 除数quotient dw 0 ; 商remainder dw 0 ; 余数section .textglobal _start_start:mov ax, [dividend] ; 将被除数存储在寄存器ax中mov bx, [divisor] ; 将除数存储在寄存器bx中div bx ; 进行除法运算mov [quotient], ax ; 将商存储在指定位置mov [remainder], dx ; 将余数存储在指定位置; 在这里可以进行其他操作,比如打印结果等mov eax, 1 ; 退出程序xor ebx, ebxint 0x80```在上面的程序中,我们首先定义了四个变量:被除数dividend、除数divisor、商quotient和余数remainder。

然后,我们将被除数和除数分别存储在寄存器ax和bx中,使用div指令进行除法运算,并将商和余数存储在指定位置。

汇编基础程序编写教程示例

汇编基础程序编写教程示例

汇编基础程序编写教程⽰例⽬录源程序1.1 构成寄存器与段的关联假设标号定义⼀个段程序结束标记程序返回程序运⾏1.2 源程序中的“程序”1.3 段结束、程序结束、程序返回1.4 语法错误和逻辑错误2 程序执⾏的过程2.1 ⼀个汇编语⾔程序从写出到最终执⾏的简要过程:2.2 连接2.3 可执⾏⽂件2.4 程序执⾏过程的跟踪总结3 程序编写3.1 两个基本的问题3.2 数据在哪⾥⽴即数(idata)寄存器段地址(SA)和偏移地址(EA)3.3 指令处理的数据有多长3.4 数据处理在代码段中使⽤数据在代码段中使⽤栈将数据、代码、栈放⼊不同的段CPU如何知道去执⾏它们?3.5 模块化实现:call 和 ret 指令retretf⽰例主要应⽤格式源程序1.1 构成寄存器与段的关联假设assume:含义为“假设”。

它假设某⼀段寄存器和程序中的某⼀个⽤ segment … ends 定义的段相关联。

通过assume说明这种关联,在需要的情况下,编译程序可以将段寄存器和某⼀个具体的段相联系。

标号⼀个标号指代了⼀个地址。

codesg:放在segment的前⾯,作为⼀个段的名称,这个段的名称最终将被编译、连接程序处理为⼀个段的段地址。

定义⼀个段segment和ends的功能是定义⼀个段,segment说明⼀个段开始,ends 说明⼀个段结束。

segment和ends是⼀对成对使⽤的伪指令⼀个段必须有⼀个名称来标识,使⽤格式为:段名 segment段名 ends⼀个汇编程序是由多个段组成的,这些段被⽤来存放代码、数据或当作栈空间来使⽤。

⼀个有意义的汇编程序中⾄少要有⼀个段,这个段⽤来存放代码。

程序结束标记End 是⼀个汇编程序的结束标记,编译器在编译汇编程序的过程中,如果碰到了伪指令 end,就结束对源程序的编译。

如果程序写完了,要在结尾处加上伪指令end 。

否则,编译器在编译程序时,⽆法知道程序在何处结束。

注意:不要搞混了end和ends。

第4章汇编语言程序设计及编程实例

第4章汇编语言程序设计及编程实例
汇编(汇编程序) 汇编(汇编程序)
源程序 汇编语言) (汇编语言)
反汇编(汇编程序) 反汇编(汇编程序)
目标码 机器语言) (机器语言)
§4. 3 汇编语言程序的基本结构
一、顺序程序 二、分支程序 三、循环程序
一、顺序程序
顺序程序是最简单的程序结构,即顺序结构。 顺序程序是最简单的程序结构,即顺序结构。 程序按顺序一条一条地执行指令 程序按顺序一条一条地执行指令。 按顺序一条一条
1、程序功能模块化的优点 、
单个模块结构的程序功能单一,易于编写、 单个模块结构的程序功能单一,易于编写、调试和修 改。 便于分工, 便于分工,从而可使多个程序员同时进行程序的编写 和调试工作,加快软件研制进度。 和调试工作,加快软件研制进度。 程序可读性好,便于功能扩充和版本升级。 程序可读性好,便于功能扩充和版本升级。 对程序的修改可局部进行,其它部分可以保持不变。 对程序的修改可局部进行,其它部分可以保持不变。 对于使用频繁的子程序可以建立子程序库, 对于使用频繁的子程序可以建立子程序库,便于多个 模块调用。 模块调用。
一、手工汇编
通过手工方式查指令编码表, 通过手工方式查指令编码表,逐个把助记符指令 翻译”成机器码, “翻译”成机器码,然后把得到的机器码程序键入 单片机,进行调试和运行。 单片机,进行调试和运行。 手工汇编的缺点: 手工汇编的缺点: 1、偏移量的计算容易出错; 、偏移量的计算容易出错 2、程序的修改会引起后面指令地址的变化,转移 、程序的修改会引起后面指令地址的变化, 指令的偏移量也要重新计算。 指令的偏移量也要重新计算。
注释
注释部分不是汇编语言的功能部分, 注释部分不是汇编语言的功能部分,只是用 于增加程序的可读性。 于增加程序的可读性。 良好的注释是汇编语言程序编写中的重要组 成部分。 成部分。源自§4.1.2 编程的方法和技巧

精选10个汇编语言程序案例集

精选10个汇编语言程序案例集

精选10个汇编语言程序案例集摘要:一、汇编语言简介二、案例1:简单算术运算三、案例2:字符串处理四、案例3:逻辑与关系运算五、案例4:循环与条件语句六、案例5:函数调用与参数传递七、案例6:数组与指针操作八、案例7:内存管理九、案例8:输入输出操作十、案例9:操作系统调用十一、案例10:网络编程十二、总结与拓展正文:一、汇编语言简介汇编语言是一种低级编程语言,它与计算机硬件的操作紧密相关。

汇编语言通过对计算机指令进行汇编,实现对计算机资源的控制。

下面将介绍10个汇编语言程序案例。

二、案例1:简单算术运算案例1是一个实现加减乘除算术运算的汇编程序。

通过编写相应的汇编指令,实现对两个整数的加减乘除操作。

三、案例2:字符串处理案例2是一个处理字符串的汇编程序。

通过汇编指令实现字符串的输入、输出、查找、替换等功能。

四、案例3:逻辑与关系运算案例3是一个处理逻辑与关系运算的汇编程序。

通过汇编指令实现逻辑与、逻辑或、逻辑非以及关系运算。

五、案例4:循环与条件语句案例4是一个处理循环与条件语句的汇编程序。

通过汇编指令实现for、while、if-else等循环与条件控制结构。

六、案例5:函数调用与参数传递案例5是一个处理函数调用与参数传递的汇编程序。

通过汇编指令实现函数调用,以及将参数传递给函数。

七、案例6:数组与指针操作案例6是一个处理数组与指针操作的汇编程序。

通过汇编指令实现数组的创建、访问、排序等操作,以及指针的运算与控制。

八、案例7:内存管理案例7是一个处理内存管理的汇编程序。

通过汇编指令实现内存的分配、释放、拷贝等操作。

九、案例8:输入输出操作案例8是一个处理输入输出操作的汇编程序。

通过汇编指令实现键盘输入、显示输出等功能。

十、案例9:操作系统调用案例9是一个处理操作系统调用的汇编程序。

通过汇编指令实现操作系统提供的功能,如文件操作、进程管理等。

十一、案例10:网络编程案例10是一个处理网络编程的汇编程序。

汇编语言编程实例

汇编语言编程实例

汇编语言编程实例一、引言汇编语言是计算机硬件和软件之间的桥梁,它是一种低级语言,可以直接控制计算机硬件。

汇编语言编程可以让程序员更加深入地理解计算机的工作原理,从而实现更高效的程序。

本文将介绍几个汇编语言编程实例,涉及到基本的输入输出、循环、条件判断、数组等知识点。

在这些实例中,我们将使用NASM汇编器进行编译和链接。

二、基本输入输出1. 输出字符串在汇编语言中,我们可以使用系统调用来进行输入输出操作。

在Linux 系统中,输出字符串的系统调用为write。

下面是一个输出字符串的示例程序:```section .datamsg db 'Hello, World!',0xa ;定义一个字符串len equ $-msg ;获取字符串长度section .textglobal _start_start:mov eax, 4 ;write系统调用号为4mov ebx, 1 ;文件描述符为1(标准输出)mov ecx, msg ;要输出的字符串地址mov edx, len ;要输出的字符数int 0x80 ;调用系统调用mov eax, 1 ;exit系统调用号为1xor ebx, ebx ;退出状态码为0int 0x80 ;调用系统调用退出程序```2. 输入数字类似地,在Linux系统中,输入数字的系统调用为read。

下面是一个输入数字的示例程序:```section .datamsg db 'Please enter a number: ',0xa ;提示信息len equ $-msg ;获取字符串长度buf resb 1 ;定义一个字节的缓冲区section .textglobal _start_start:mov eax, 4 ;write系统调用号为4mov ebx, 1 ;文件描述符为1(标准输出)mov ecx, msg ;要输出的字符串地址mov edx, len ;要输出的字符数int 0x80 ;调用系统调用mov eax, 3 ;read系统调用号为3mov ebx, 0 ;文件描述符为0(标准输入)mov ecx, buf ;缓冲区地址mov edx, 1 ;要读取的字节数int 0x80 ;调用系统调用sub al, '0' ;将ASCII码转换成数字值```三、循环和条件判断1. 计算1到100的和下面是一个计算1到100的和的示例程序,其中使用了循环和条件判断:```section .datasum dd 0 ;定义一个双精度浮点型变量sumsection .textglobal _start_start:xor eax, eax ;eax清零,作为计数器和累加器使用loop_start:inc eax ;eax自增1,相当于i++cmp eax, 100+1 ;比较i是否大于100,注意要加1je loop_end ;如果i等于101,跳转到loop_endadd dword [sum], eax ;将i加到sum中jmp loop_start ;跳转到loop_startloop_end:mov eax, dword [sum] ;将sum赋值给eax,作为返回值mov ebx, 1 ;exit系统调用号为1int 0x80 ;调用系统调用退出程序```2. 判断一个数是否为素数下面是一个判断一个数是否为素数的示例程序,其中使用了循环和条件判断:```section .datamsg db 'Please enter a number: ',0xa ;提示信息len equ $-msg ;获取字符串长度buf resb 1 ;定义一个字节的缓冲区section .textglobal _start_start:mov eax, 4 ;write系统调用号为4mov ebx, 1 ;文件描述符为1(标准输出)mov ecx, msg ;要输出的字符串地址mov edx, len ;要输出的字符数int 0x80 ;调用系统调用mov eax, 3 ;read系统调用号为3mov ebx, 0 ;文件描述符为0(标准输入)mov ecx, buf ;缓冲区地址mov edx, 1 ;要读取的字节数int 0x80 ;调用系统调用sub al, '0' ;将ASCII码转换成数字值check_prime:xor ebx, ebx ;ebx清零,作为除数使用mov ecx, eax ;将eax的值赋给ecx,作为被除数使用inc ebx ;将ebx自增1,相当于除数加1cmp ebx, ecx ;比较除数是否大于被除数jge is_prime ;如果除数大于等于被除数,跳转到is_prime xor edx, edx ;edx清零,作为余数使用div ebx ;将ecx/ebx的商放在eax中,余数放在edx中 cmp edx, 0 ;判断余数是否为0je not_prime ;如果余数为0,跳转到not_primejmp check_prime ;跳转到check_primenot_prime:mov eax, 4 ;write系统调用号为4mov ebx, 1 ;文件描述符为1(标准输出)mov ecx, not_prime_msg ;要输出的字符串地址mov edx, not_prime_len ;要输出的字符数int 0x80 ;调用系统调用exit:mov eax, 1 ;exit系统调用号为1xor ebx, ebx ;退出状态码为0int 0x80 ;调用系统调用退出程序not_prime_msg db 'The number is not prime.',0xa ;提示信息not_prime_len equ $-not_prime_msgis_prime:mov eax, 4 ;write系统调用号为4mov ebx, 1 ;文件描述符为1(标准输出)mov ecx, is_prime_msg ;要输出的字符串地址mov edx, is_prime_len ;要输出的字符数int 0x80 ;调用系统调用jmp exit ;跳转到exitis_prime_msg db 'The number is prime.',0xa ;提示信息is_prime_len equ $-is_prime_msg```四、数组1. 计算数组的和下面是一个计算数组的和的示例程序:```section .dataarr dd 1, 2, 3, 4, 5 ;定义一个双精度浮点型数组arrn equ ($-arr)/4 ;获取数组长度section .textglobal _start_start:xor eax, eax ;eax清零,作为计数器和累加器使用xor ecx, ecx ;ecx清零,作为数组下标使用loop_start:cmp ecx, n ;比较ecx是否大于等于njge loop_end ;如果ecx大于等于n,跳转到loop_endadd eax, dword [arr+ecx*4] ;将arr[ecx]加到eax中inc ecx ;将ecx自增1,相当于下标加1jmp loop_start ;跳转到loop_startloop_end:mov ebx, eax ;将sum赋值给ebx,作为返回值mov eax, 1 ;exit系统调用号为1xor ecx, ecx ;退出状态码为0int 0x80 ;调用系统调用退出程序```2. 查找数组中的最大值下面是一个查找数组中的最大值的示例程序:```section .dataarr dd 10,20,30,-40,-50,-60,-70,-80,-90,-100 ;定义一个双精度浮点型数组arrn equ ($-arr)/4 ;获取数组长度section .textglobal _start_start:mov eax, dword [arr] ;将arr[0]赋值给eax,作为最大值使用xor ecx, ecx ;ecx清零,作为数组下标使用loop_start:cmp ecx, n ;比较ecx是否大于等于njge loop_end ;如果ecx大于等于n,跳转到loop_endcmp eax, dword [arr+ecx*4] ;比较eax和arr[ecx]jge loop_next ;如果eax大于等于arr[ecx],跳转到loop_next mov eax, dword [arr+ecx*4] ;将arr[ecx]赋值给eax,更新最大值loop_next:inc ecx ;将ecx自增1,相当于下标加1jmp loop_start ;跳转到loop_startloop_end:mov ebx, eax ;将max赋值给ebx,作为返回值mov eax, 1 ;exit系统调用号为1xor ecx, ecx ;退出状态码为0int 0x80 ;调用系统调用退出程序```五、总结本文介绍了几个汇编语言编程实例,涉及到基本的输入输出、循环、条件判断、数组等知识点。

汇编编程实例

汇编编程实例
mov ah,10
int 21h
mov cl, [buf+1]
lea di,buf+2
call datacate
call ifyears
jc a1
yjw1: JMP B1
A2: MOV DL,WW ;显示'-'
MOV AH,2
INT 21H
mov cx,65535
mai1: loop mai1
CALL RAND1
CALL MCAT
loop l1
ret
datacate endp
ifyears proc near
push bx
push cx
push dx
mov ax,w
PUSH AX
STI
MOV AH,0
INT 1AH
MOV ax,cx
AND AH,3
MOV DL,101
DIV DL
MOV BL,AH
POP AX
POP DX
PUSH CX
PUSH DX
mov ax,bx
mov bl,5
div bl
cmp ah,3
jae vb1
mov www,1
jmp vn1
vb1:mov www,0
vn1:pop dx
pop cx
案例1判断闰年程序
data segment ;定义数据段
infon db 0dh,0ah,'Please input a year: $'
Y db 0dh,0ah,'This is a leap year! $'

汇编语言指令大全及实例解析

汇编语言指令大全及实例解析

汇编语言指令大全及实例解析
汇编语言是一种底层的计算机语言,它直接操作计算机的硬件资源。

在汇编语言中,指令是最基本的操作单位,通过指令可以实现对计算机硬件的控制和操作。

本文将为大家介绍一些常用的汇编语言指令,并通过实例解析它们的具体用法和功能。

1. MOV指令。

MOV指令用于将数据从一个位置复制到另一个位置。

例如,下面的汇编代码将把寄存器AX中的值移动到寄存器BX中:
MOV BX, AX.
这条指令将AX中的值复制到BX中。

2. ADD指令。

ADD指令用于将两个操作数相加,并将结果存储到目标操作数中。

例如,下面的汇编代码将把寄存器AX和BX中的值相加,并将结果存储到AX中:
ADD AX, BX.
3. SUB指令。

SUB指令用于将目标操作数减去源操作数,并将结果存储到目标操作数中。

例如,下面的汇编代码将把寄存器AX中的值减去BX 中的值,并将结果存储到AX中:
SUB AX, BX.
4. CMP指令。

CMP指令用于比较两个操作数的大小,并根据比较结果设置标志位。

例如,下面的汇编代码将比较AX和BX中的值:
CMP AX, BX.
以上是一些常用的汇编语言指令及其实例解析。

通过学习和理解这些指令,我们可以更好地理解和掌握汇编语言的编程技巧,从而更好地编写高效的汇编语言程序。

希望本文对大家有所帮助。

汇编语言程序案例 -回复

汇编语言程序案例 -回复

汇编语言程序案例-回复下面是一个简单的汇编语言程序案例,实现累加1到n的功能。

section .datainputMsg db "请输入一个正整数: ", 0outputMsg db "累加结果为: ", 0inputNum db ?section .textglobal _start_start:; 输出提示消息,要求输入一个正整数mov eax, 4mov ebx, 1mov ecx, inputMsgmov edx, 16int 0x80; 读取用户输入的正整数mov eax, 3mov ebx, 0mov ecx, inputNummov edx, 1int 0x80; 初始化累加变量为0mov eax, 0mov esi, 1 ; esi用来保存当前要加的数字mov edi, [inputNum] ; edi用来保存用户输入的正整数add_loop:; 判断当前要加的数字是否小于等于用户输入的正整数cmp esi, edijnle add_done; 累加当前的数字add eax, esi; 当前的数字加1,继续下一个循环inc esijmp add_loopadd_done:; 输出累加结果mov eax, 4mov ebx, 1mov ecx, outputMsgmov edx, 12int 0x80mov eax, 4mov ebx, 1mov ecx, eaxmov edx, 2 ; edx为2表示输出eax寄存器的前两个字节add ecx, edxsub ecx, 1 ; ecx减去1,以输出累加结果的最后一个数字mov edx, 1int 0x80; 退出程序mov eax, 1xor ebx, ebxint 0x80该程序会首先输出提示消息要求用户输入一个正整数,然后读取用户输入的正整数。

接着,程序会使用循环来累加从1到用户输入的正整数的结果,并将结果输出。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

汇编语言编程实例一这一章,我们要把我们已学的知识集合起来。

具体来讲,我们来写一个使用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,stdcallinclude \masm32\include\windows.incinclude \masm32\include\kernel32.incinclude \masm32\include\odbc32.incinclude \masm32\include\comctl32.incinclude \masm32\include\user32.incincludelib \masm32\lib\odbc32.libincludelib \masm32\lib\comctl32.libincludelib \masm32\lib\kernel32.libincludelib \masm32\lib\user32.libIDD_MAINDLG equ 101IDR_MAINMENU equ 102IDC_DATALIST equ 1000IDM_CONNECT equ 40001IDM_DISCONNECT equ 40002IDM_QUERY equ 40003IDC_NAME equ 1000IDC_OK equ 1001IDC_CANCEL equ 1002IDM_CUSTOMQUERY equ 40004IDD_QUERYDLG equ 102DlgProc proto hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORDQueryProc proto hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD SwitchMenuState proto :DWORDODBCConnect proto :DWORDODBCDisconnect proto :DWORDRunQuery 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(?).dataSQLStatement db "select * from main",0WhereStatement db " where name=?",0strConnect db "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=",0 DBName db "test.mdb",0ConnectCaption db "Complete Connection String",0Disconnect db "Disconnect successful",0AppName db "ODBC Test",0AllocEnvFail db "Environment handle allocation failed",0 AllocConnFail db "Connection handle allocation failed",0 SetAttrFail db "Cannot set desired ODBC version",0NoData db "You must type the name in the edit box",0ExecuteFail db "Execution of SQL statement failed",0ConnFail db "Connection attempt failed",0AllocStmtFail db "Statement handle allocation failed",0Heading1 db "Name",0Heading2 db "Surname",0Heading3 db "Telephone No.",0.codestart:invoke GetModuleHandle, NULLmov hInstance,eaxcall GetProgramPathinvoke DialogBoxParam, hInstance, IDD_MAINDLG,0,addr DlgProc,0invoke ExitProcess,eaxinvoke InitCommonControlsDlgProc proc hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD.if uMsg==WM_INITDIALOGinvoke GetMenu, hDlgmov hMenu,eaxinvoke GetDlgItem, hDlg, IDC_DATALISTmov hList,eaxcall InsertColumn.elseif uMsg==WM_CLOSEinvoke GetMenuState, hMenu, IDM_CONNECT,MF_BYCOMMAND.if eax==MF_GRAYEDinvoke ODBCDisconnect, hDlg.endifinvoke EndDialog,hDlg, 0.elseif uMsg==WM_COMMAND.if lParam==0mov eax,wParam.if ax==IDM_CONNECTinvoke ODBCConnect,hDlg.elseif ax==IDM_DISCONNECTinvoke ODBCDisconnect,hDlg.elseif ax==IDM_QUERYinvoke RunQuery,hDlg.elseif ax==IDM_CUSTOMQUERYinvoke DialogBoxParam, hInstance, IDD_QUERYDLG,hDlg, addr QueryProc, 0 .endif.endif.elsemov eax,FALSEret.endifmov eax,TRUEretDlgProc endpGetProgramPath procinvoke GetModuleFileName, NULL,addr ProgPath,sizeof ProgPathstdmov edi,offset ProgPathadd edi,sizeof ProgPath-1mov al,"\"mov ecx,sizeof ProgPathrepne scasbcldmov byte ptr [edi+2],0retGetProgramPath endpSwitchMenuState proc Flag:DWORD.if Flag==TRUEinvoke EnableMenuItem, hMenu, IDM_CONNECT, MF_GRAYEDinvoke EnableMenuItem, hMenu, IDM_DISCONNECT, MF_ENABLEDinvoke EnableMenuItem, hMenu, IDM_QUERY, MF_ENABLEDinvoke EnableMenuItem, hMenu, IDM_CUSTOMQUERY, MF_ENABLED.elseinvoke EnableMenuItem, hMenu, IDM_CONNECT, MF_ENABLEDinvoke EnableMenuItem, hMenu, IDM_DISCONNECT, MF_GRAYEDinvoke EnableMenuItem, hMenu, IDM_QUERY, MF_GRAYEDinvoke EnableMenuItem, hMenu, IDM_CUSTOMQUERY, MF_GRAYED.endifretSwitchMenuState endpODBCConnect proc hDlg:DWORDinvoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_NULL_HANDLE, addr hEnv.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFOinvoke SQLSetEnvAttr, hEnv,SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3,0.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFOinvoke SQLAllocHandle, SQL_HANDLE_DBC, hEnv, addr hConn.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFOinvoke lstrcpy,addr ConnectString,addr strConnectinvoke lstrcat,addr ConnectString, addr ProgPathinvoke lstrcat, addr ConnectString,addr DBNameinvoke SQLDriverConnect, hConn, hDlg, addr ConnectString, sizeof ConnectString, addr Conn, sizeof Conn,addr StrLen, SQL_DRIVER_COMPLETE.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFOinvoke SwitchMenuState,TRUEinvoke MessageBox,hDlg, addr Conn,addr ConnectCaption,MB_OK+MB_ICONINFORMATION .elseinvoke SQLFreeHandle, SQL_HANDLE_DBC, hConninvoke SQLFreeHandle, SQL_HANDLE_ENV, hEnvinvoke MessageBox, hDlg, addr ConnFail, addr AppName, MB_OK+MB_ICONERROR.endif.elseinvoke SQLFreeHandle, SQL_HANDLE_ENV, hEnvinvoke MessageBox, hDlg, addr AllocConnFail, addr AppName, MB_OK+MB_ICONERROR .endif.elseinvoke SQLFreeHandle, SQL_HANDLE_ENV, hEnvinvoke MessageBox, hDlg, addr SetAttrFail, addr AppName, MB_OK+MB_ICONERROR.endif.elseinvoke MessageBox, hDlg, addr AllocEnvFail, addr AppName, MB_OK+MB_ICONERROR .endifretODBCConnect endpODBCDisconnect proc hDlg:DWORDinvoke SQLDisconnect, hConninvoke SQLFreeHandle, SQL_HANDLE_DBC, hConninvoke SQLFreeHandle, SQL_HANDLE_ENV, hEnvinvoke SwitchMenuState, FALSEinvoke ShowWindow,hList, SW_HIDEinvoke MessageBox,hDlg,addr Disconnect, addr AppName,MB_OK+MB_ICONINFORMATION retODBCDisconnect endpInsertColumn procLOCAL lvc:LV_COLUMNmov lvc.imask,LVCF_TEXT+LVCF_WIDTHmov lvc.pszText,offset Heading1mov lvc.lx,150invoke SendMessage,hList, LVM_INSERTCOLUMN,0,addr lvcmov lvc.pszText,offset Heading2invoke SendMessage,hList, LVM_INSERTCOLUMN, 1 ,addr lvcmov lvc.pszText,offset Heading3invoke SendMessage,hList, LVM_INSERTCOLUMN, 3 ,addr lvcretInsertColumn endpFillData procLOCAL lvi:LV_ITEMLOCAL row:DWORDinvoke SQLBindCol, hStmt,1,SQL_C_CHAR, addr TheName, sizeof TheName,addr NameLe ngthinvoke SQLBindCol, hStmt,2,SQL_C_CHAR, addr TheSurname, sizeof TheSurname,addr SurnameLengthinvoke SQLBindCol, hStmt,3,SQL_C_CHAR, addr TelNo, sizeof TelNo,addr TelNoLengt hmov row,0.while TRUEmov byte ptr ds:[TheName],0mov byte ptr ds:[TheSurname],0mov byte ptr ds:[TelNo],0invoke SQLFetch, hStmt.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFOmov lvi.imask,LVIF_TEXT+LVIF_PARAMpush rowpop lvi.iItemmov lvi.iSubItem,0mov lvi.pszText, offset TheNamepush rowpop lvi.lParaminvoke SendMessage,hList, LVM_INSERTITEM,0, addr lvimov lvi.imask,LVIF_TEXTinc lvi.iSubItemmov lvi.pszText,offset TheSurnameinvoke SendMessage,hList,LVM_SETITEM, 0,addr lviinc lvi.iSubItemmov lvi.pszText,offset TelNoinvoke SendMessage,hList,LVM_SETITEM, 0,addr lviinc row.else.break.endif.endwretFillData endpRunQuery proc hDlg:DWORDinvoke ShowWindow, hList, SW_SHOWinvoke SendMessage, hList, LVM_DELETEALLITEMS,0,0invoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFOinvoke SQLExecDirect, hStmt, addr SQLStatement, sizeof SQLStatement.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFOinvoke FillData.elseinvoke ShowWindow, hList, SW_HIDEinvoke MessageBox,hDlg,addr ExecuteFail, addr AppName, MB_OK+MB_ICONERROR .endifinvoke SQLCloseCursor, hStmtinvoke SQLFreeHandle, SQL_HANDLE_STMT, hStmt.elseinvoke ShowWindow, hList, SW_HIDEinvoke MessageBox,hDlg,addr AllocStmtFail, addr AppName, MB_OK+MB_ICONERROR .endifretRunQuery endpQueryProc proc hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD.if uMsg==WM_CLOSEinvoke SQLFreeHandle, SQL_HANDLE_STMT, hStmtinvoke EndDialog, hDlg,0.elseif uMsg==WM_INITDIALOGinvoke ShowWindow, hList, SW_SHOWinvoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFOinvoke lstrcpy, addr Conn, addr SQLStatementinvoke lstrcat, addr Conn, addr WhereStatementinvoke SQLBindParameter,hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,25,0, a ddr SearchName,25,addr StrLeninvoke SQLPrepare, hStmt, addr Conn, sizeof Conn.elseinvoke ShowWindow, hList, SW_HIDEinvoke MessageBox,hDlg,addr AllocStmtFail, addr AppName, MB_OK+MB_ICONERROR invoke EndDialog, hDlg,0.endif.elseif uMsg==WM_COMMANDmov eax, wParamshr eax,16.if ax==BN_CLICKEDmov eax,wParam.if ax==IDC_OKinvoke GetDlgItemText, hDlg, IDC_NAME, addr SearchName, 25.if ax==0invoke MessageBox, hDlg,addr NoData, addr AppName, MB_OK+MB_ICONERRORinvoke GetDlgItem, hDlg, IDC_NAMEinvoke SetFocus, eax.elseinvoke lstrlen,addr SearchNamemov StrLen,eaxinvoke SendMessage, hList, LVM_DELETEALLITEMS,0,0invoke SQLExecute, hStmtinvoke FillDatainvoke SQLCloseCursor, hStmt.endif.elseinvoke SQLFreeHandle, SQL_HANDLE_STMT, hStmtinvoke EndDialog, hDlg,0.endif.endif.elsemov eax,FALSEret.endifmov eax,TRUEretQueryProc endpend start分析start:invoke GetModuleHandle, NULLmov hInstance,eaxcall GetProgramPath当程序开始时,将获得实例句柄并获得所在路径.默认情况下数据库 test.mdb应与程序处于同一文件夹.GetProgramPath procinvoke GetModuleFileName, NULL,addr ProgPath,sizeof ProgPathstdmov edi,offset ProgPathadd edi,sizeof ProgPath-1mov al,"\"mov ecx,sizeof ProgPathrepne scasbcldmov byte ptr [edi+2],0retGetProgramPath endpGetProgramPath调用GetModuleFileName来获得程序的全路径名.接着在路径中查找最后一个"\"符",通过将文件名的第一个字符置为0获得(truncate)" 文件名. 因此我们在Pr ogPath中获得了程序的路径名.然后程序将用DialogBoxParam显示主对话框.当主对话框第一次被载入时,它将获得菜单句柄和listview control句柄.接下来在listview control中插入三列(因为我们已经知道结果集将包含三列.因为是我们先建的表.)现在,它就等待用户的动作了.如果用户在菜单中选择"connect",将会调用ODBCConnec t函数.ODBCConnect proc hDlg:DWORDinvoke 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 strConnectinvoke lstrcat,addr ConnectString, addr ProgPathinvoke lstrcat, addr ConnectString,addr DBName接着填写连接字符串.完整的连接字符串将被用在ConnectionStringinvoke SQLDriverConnect, hConn, hDlg, addr ConnectString, sizeof ConnectString, addr Conn, sizeof Conn,addr StrLen, SQL_DRIVER_COMPLETE.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFOinvoke SwitchMenuState,TRUEinvoke 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:DWORDinvoke ShowWindow, hList, SW_SHOWinvoke 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 procLOCAL lvi:LV_ITEMLOCAL row:DWORDinvoke SQLBindCol, hStmt,1,SQL_C_CHAR, addr TheName, sizeof TheName,addr NameLe ngthinvoke SQLBindCol, hStmt,2,SQL_C_CHAR, addr TheSurname, sizeof TheSurname,addr SurnameLengthinvoke SQLBindCol, hStmt,3,SQL_C_CHAR, addr TelNo, sizeof TelNo,addr TelNoLengt h现在,结果集被返回.我们要绑定结果集的所有三列到我们提供的缓冲区中.这是调用S QLBindCol来实现的.注意我们要对每一列分别调用.并且我们并不需要绑定所有的列:只要绑定要获得数据的列就行了.mov row,0.while TRUEmov byte ptr ds:[TheName],0mov byte ptr ds:[TheSurname],0mov byte ptr ds:[TelNo],0当列中没有数据时,我们初始化缓冲区为NULLs.更好的方法是用SQLBindCol指定的变量中数据的长度.在我们的例子中,我们可以检查NameLength, SurnameLength和TelNoLeng th中的值的确切长度.invoke SQLFetch, hStmt.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFOmov lvi.imask,LVIF_TEXT+LVIF_PARAMpush rowpop lvi.iItemmov lvi.iSubItem,0mov lvi.pszText, offset TheNamepush rowpop lvi.lParaminvoke SendMessage,hList, LVM_INSERTITEM,0, addr lvi其它都很简单了.调用SQLFetch 来获得结果集的一行,并将其存入listview control 的缓冲区中.当没有更多的行供检索时(已到达文件尾), SQLFetch返回SQL_NO_DATA并且程序跳出循环.invoke SQLCloseCursor, hStmtinvoke SQLFreeHandle, SQL_HANDLE_STMT, hStmt当完成对结果集的操作时,调用SQLCloseCursor关闭结果集并调用SQLFreeHandle释放语句句柄.当用户选择"Query"命令,程序显示另一个对话框供用户输入要查询的名字..elseif uMsg==WM_INITDIALOGinvoke ShowWindow, hList, SW_SHOWinvoke SQLAllocHandle, SQL_HANDLE_STMT, hConn, addr hStmt.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFOinvoke lstrcpy, addr Conn, addr SQLStatementinvoke lstrcat, addr Conn, addr WhereStatementinvoke SQLBindParameter,hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,25,0, a ddr SearchName,25,addr StrLeninvoke 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_OKinvoke GetDlgItemText, hDlg, IDC_NAME, addr SearchName, 25.if ax==0invoke MessageBox, hDlg,addr NoData, addr AppName, MB_OK+MB_ICONERRORinvoke GetDlgItem, hDlg, IDC_NAMEinvoke SetFocus, eax.else当用户在编辑框(edit control)中填入了一些名字并按下回车键, 程序将获得编辑框中的文本并检查是否是空字符串.如果是,则显示一个message box并将键盘焦点设在编辑框上,提示用户输入名字.invoke lstrlen,addr SearchNamemov StrLen,eaxinvoke SendMessage, hList, LVM_DELETEALLITEMS,0,0invoke SQLExecute, hStmtinvoke FillDatainvoke SQLCloseCursor, hStmt如果编辑框中已有字符串,程序会获得它的长度并将其放入StrLen中供ODBC驱动程序使用(记住我们已将StrLen的地址传送给了SQLBindParameter). 接下来程序使用获得的语句句柄调用SQLExecute执行已准备好的SQL语句.当 SQLExecute返回时,程序调用FillDa ta在listview control显示结果.因为我们不会再用到结果集,调用SQLCloseCursor来关闭它.。

相关文档
最新文档