要在汇编中使用SQLite数据库,就得使用SQLite的库文件,可以有两种方式调用SQLite的一些库函数,一种是使用SQLite的dll文件,通过动态加载的方式用系统的API获取里面的库函数。另一种方式是使用SQLite的lib文件,自己在代码中编写SQLite的相关函数原型,进而调用SQLite库里的函数。这里使用动态加载库文件的方式来完成相关函数的调用。
1.在汇编中动态加载库文件
通过动态加载库文件方式来使用库函数要用到三个函数:LoadLibary(装入动态链接库),FreeLibrary(释放动态链接库)以及GetProcAddress(获取导出函数地址)。LoadLibrary函数的使用方法是:
invoke LoadLibrary,lpDllFileName
.if eax
mov hDllInstance,eax
.endif
参数lpDllFileName指向需要装载的库文件名称,库文件名称以0结尾。函数会按照当前目录、Windows系统目录和PATH环境变量列出的目录查找库文件,先搜索到的库文件会被装入。装入成功函数返回动态链接库的句柄,失败则返回NULL。
装载动态链接库成功后,就可以使用GetProcAddress函数来获取库中函数的地址。GetProcAddress函数的使用方法是:
invoke GetProcAddress,hDllInstance,lpProcName
.if eax
mov lpProc,eax
.endif
hDllInstance参数就是LoadLibrary函数返回的动态链接库的句柄,lpProcName指向要获取的函数名称,函数名称以0结尾,对于函数名称是数值编号的lpProcName可以指定为编号数值。函数执行成功则返回要获取的函数的入口地址,失败则返回NULL。
不在需要动态链接库的时候就需要使用FreeLibrary函数来释放它。FreeLibrary的用法是:
invoke FreeLibrary,hDllInstance
输入参数是LoadLibrary函数返回的动态链接库的句柄。
2.使用SQLite数据库
要使用SQLite数据库,需要sqlite3.h和sqlite3.dll这两个文件。在sqlite3.h头文件中,我们可以查看一些预定义值以及函数原型的定义。sqlite3.dll中则包含需要用到的库函数。这两个文件都可以在SQLite官网下载。
经常使用的SQLite库函数主要有四个,分别是sqlite3_open(打开数据库文件),sqlite3_close(关闭数据库文件),sqlite3_exec(执行SQL语句)以及sqlite3_get_table(执行查询语句获得数据表)。这几个函数的具体使用方法可以参照sqlite入门基础。
在.const数据段中,需要定义装入的库文件名,函数名以及数据库文件名:
.const
;SQLite相关信息*****************************************************************************
libName db 'sqlite3.dll',0
sqlite3_open db 'sqlite3_open',0
sqlite3_close db 'sqlite3_close',0
sqlite3_exec db 'sqlite3_exec',0
sqlite3_slct db 'sqlite3_get_table',0
fileName db 'data.db',0
在使用GetProcAddress函数获取到库函数的入口点的地址后,我们可以手动将参数入栈,然后用call指令调用函数。但这样就不能用invoke伪指令来进行参数检查,容易发生错误。我们可以采用将一个变量定义为函数入口指针,并为它定义参数个数,在数据段中可以将保存函数入口参数的变量使用函数指针来定义,这样就能够用invoke语句来调用这个变量中的指针:
;SQLite相关函数指针定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
sql_open typedef proto :dword,:dword
SQL_Open typedef ptr sql_open
sql_close typedef proto :dword
SQL_Close typedef ptr sql_close
callback typedef proto :dword,:dword,:dword,:dword
CallBack typedef ptr callback
sql_exec typedef proto :dword,:dword,:CallBack,:dword,:dword
SQL_Exec typedef ptr sql_exec
sql_slct typedef proto :dword,:dword,:dword,:dword,:dword,:dword
SQL_Slct typedef ptr sql_slct
.data?
;SQLite相关信息
hs_open SQL_Open ?
hs_close SQL_Close ?
hs_exec SQL_Exec ?
hs_slct SQL_Slct ?
有了SQLite的库函数的指针之后就能够像使用这些函数完成相应的功能了,以下是一个完整的数据库使用代码,实现了数据库表的创建,数据的插入已经两种方式进行数据查询。需要注意的是使用LoadLibary函数和GetProcAddress函数,应该要对返回值进行检查,因为一旦失败,很容易引发调用NULL指针的错误。下面这段代码为了简化,并没有检查指针是否为NULL。代码中有计算字符串长度,复制字符串和拼接字符串的辅助函数。
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;include文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;SQLite相关函数指针定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
sql_open typedef proto :dword,:dword
SQL_Open typedef ptr sql_open
sql_close typedef proto :dword
SQL_Close typedef ptr sql_close
callback typedef proto :dword,:dword,:dword,:dword
CallBack typedef ptr callback
sql_exec typedef proto :dword,:dword,:CallBack,:dword,:dword
SQL_Exec typedef ptr sql_exec
sql_slct typedef proto :dword,:dword,:dword,:dword,:dword,:dword
SQL_Slct typedef ptr sql_slct
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstance dd ?
;SQLite相关信息*****************************************************************************
hLib dd ?
hDB dd ?
errorInfo dd ?
hs_open SQL_Open ?
hs_close SQL_Close ?
hs_exec SQL_Exec ?
hs_slct SQL_Slct ?
.const
;SQLite相关信息*****************************************************************************
libName db 'sqlite3.dll',0
sqlite3_open db 'sqlite3_open',0
sqlite3_close db 'sqlite3_close',0
sqlite3_exec db 'sqlite3_exec',0
sqlite3_slct db 'sqlite3_get_table',0
fileName db 'data.db',0
createTable db 'create table if not exists Data(id integer primary key autoincrement,'
db 'stuno varchar(30),name varchar(60))',0
insertData db 'insert into Data(stuno,name) values(',39,'10211124',39,','
db 39,'李四',39,')',0
selectData db 'select * from Data',0
split db ':',0
endline db 0dh,0ah,0
empty db 0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;计算字符串长度
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_StrLen proc uses ebx ecx,pstr
mov ebx,pstr
mov eax,0
mov cl,[ebx]
.while cl
inc ebx
inc eax
mov cl,[ebx]
.endw
ret
_StrLen endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;计算字符串复制
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_StrCopy proc uses ebx esi,src
local @strAddr,@len
invoke _StrLen,src
inc eax
invoke GlobalAlloc,GPTR,eax
mov @strAddr,eax
mov ebx,eax
mov esi,src
mov al,[esi]
.while al
mov [ebx],al
inc ebx
inc esi
mov al,[esi]
.endw
mov al,0
mov [ebx],al
mov eax,@strAddr
ret
_StrCopy endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;计算字符串拼接
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_StrCat proc uses ebx esi,str1,str2
local @strAddr,@len
invoke _StrLen,str1
mov @len,eax
invoke _StrLen,str2
add eax,@len
inc eax
invoke GlobalAlloc,GPTR,eax
mov @strAddr,eax
mov ebx,eax
mov esi,str1
mov al,[esi]
.while al
mov [ebx],al
inc ebx
inc esi
mov al,[esi]
.endw
mov esi,str2
mov al,[esi]
.while al
mov [ebx],al
inc ebx
inc esi
mov al,[esi]
.endw
mov al,0
mov [ebx],al
mov eax,@strAddr
ret
_StrCat endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;查询语句回调函数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
sqlcallback proc uses ebx esi edi,para,intn_column,column_value,column_name
local @str,@count
mov eax,0
mov @count,eax
mov esi,column_name
mov edi,column_value
invoke _StrCopy,offset empty
mov @str,eax
.while TRUE
invoke _StrCat,@str,[esi]
mov ebx,@str
mov @str,eax
invoke GlobalFree,ebx
invoke _StrCat,@str,offset split
mov ebx,@str
mov @str,eax
invoke GlobalFree,ebx
invoke _StrCat,@str,[edi]
mov ebx,@str
mov @str,eax
invoke GlobalFree,ebx
invoke _StrCat,@str,offset endline
mov ebx,@str
mov @str,eax
invoke GlobalFree,ebx
mov eax,@count
inc eax
mov @count,eax
.break .if eax == intn_column
add esi,4
add edi,4
.endw
invoke MessageBox,NULL,@str,offset fileName,MB_OK
invoke GlobalFree,@str
mov eax,0
ret
sqlcallback endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;查询语句执行函数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
sqlExc proc uses ebx esi edi edx
local @result,@nRow,@nCol,@str
local @i,@j,@index
invoke hs_slct,hDB,offset selectData,addr @result,addr @nRow,\
addr @nCol,offset errorInfo
invoke _StrCopy,offset empty
mov @str,eax
mov edi,@nCol
mov eax,@nRow
mov @i,eax
mov ebx,@result
.while @i
mov esi,0
.while esi < @nCol
invoke _StrCat,@str,[ebx + esi*4]
mov edx,@str
mov @str,eax
invoke GlobalFree,edx
invoke _StrCat,@str,offset split
mov edx,@str
mov @str,eax
invoke GlobalFree,edx
invoke _StrCat,@str,[ebx + edi*4]
mov edx,@str
mov @str,eax
invoke GlobalFree,edx
invoke _StrCat,@str,offset endline
mov edx,@str
mov @str,eax
invoke GlobalFree,edx
inc esi
inc edi
.endw
mov eax,@i
dec eax
mov @i,eax
.endw
invoke MessageBox,NULL,@str,offset fileName,MB_OK
invoke GlobalFree,@str
mov eax,0
ret
sqlExc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;主程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke LoadLibrary,offset libName
mov hLib,eax
invoke GetProcAddress,hLib,addr sqlite3_open
mov hs_open,eax
invoke GetProcAddress,hLib,addr sqlite3_close
mov hs_close,eax
invoke GetProcAddress,hLib,addr sqlite3_exec
mov hs_exec,eax
invoke GetProcAddress,hLib,addr sqlite3_slct
mov hs_slct,eax
invoke hs_open,offset fileName,offset hDB
invoke hs_exec,hDB,offset createTable,NULL,NULL,offset errorInfo
invoke hs_exec,hDB,offset insertData,NULL,NULL,offset errorInfo
invoke sqlExc
invoke hs_exec,hDB,offset selectData,offset sqlcallback,NULL,offset errorInfo
invoke hs_close,hDB
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start