;运行效果
;RadASM环境,win32汇编入门教程之十四
;在这一教程里,我们来学一下基本的计算,加减乘除,这个起码要知道怎么表达出来。
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
;EQU等值定义
IDB01 equ 101
IDB02 equ 102
IDB03 equ 103
IDB04 equ 104
IDB05 equ 105
ICO_MAIN equ 1000 ;图标
;函数声明
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD ;对话框窗口函数
.data
DlgName db "MyDialog",0
szMsg db "提示",0
szFrm01 db "计算结果是 %d",0
szFrm02 db "除法的结果商是 %d,余数是 %d",0
sz01 db "点击了第1个按钮",0
sz02 db "单击了第2个按钮",0
.data?
hInstance HINSTANCE ?
.const
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
invoke ExitProcess,eax
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL @szBuffer[256]:byte
LOCAL @hico
.if uMsg == WM_INITDIALOG
invoke LoadIcon,hInstance,ICO_MAIN
mov @hico,eax
invoke SendMessage,hWnd,WM_SETICON,ICON_SMALL,@hico
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,@hico
.elseif uMsg == WM_COMMAND
mov eax,wParam ;wParam的底位字节是标识符
mov ebx,lParam
.if ax == IDB01 ;进行加法运算
mov eax,11
mov ebx,22
add eax,ebx ;相当于eax+ebx,结果在eax
invoke wsprintf,addr @szBuffer,addr szFrm01,eax
invoke MessageBox,NULL,addr @szBuffer,addr szMsg,MB_OK
.elseif ax == IDB02 ;进行减法运算
mov eax,22
mov ebx,11
sub eax,ebx ;相当于eax-ebx,结果在eax
invoke wsprintf,addr @szBuffer,addr szFrm01,eax
invoke MessageBox,NULL,addr @szBuffer,addr szMsg,MB_ICONINFORMATION + MB_OK
.elseif ax == IDB03 ;进行乘法运算
mov eax,11
mov ebx,33
mul ebx ;相当于eax*ebx,结果在eax
invoke wsprintf,addr @szBuffer,addr szFrm01,eax
invoke MessageBox,NULL,addr @szBuffer,addr szMsg,MB_ICONINFORMATION + MB_OK
.elseif ax == IDB04 ;进行除法运算
mov edx,0
mov eax,4294967295
mov ebx,11
div ebx ;相当于eax/ebx,商在eax,余数在edx
invoke wsprintf,addr @szBuffer,addr szFrm02,eax,edx
invoke MessageBox,NULL,addr @szBuffer,addr szMsg,MB_ICONINFORMATION + MB_OK
.elseif ax == IDB05 ;进行除法运算
mov edx,1
mov eax,0
mov ebx,11
div ebx ;相当于eax/ebx,商在eax,余数在edx
invoke wsprintf,addr @szBuffer,addr szFrm02,eax,edx
invoke MessageBox,NULL,addr @szBuffer,addr szMsg,MB_ICONINFORMATION + MB_OK
.endif
.elseif uMsg == WM_CLOSE
invoke EndDialog, hWnd,NULL
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
end start
;在上面的内容时,有标注了加减乘除法的方式
;这些计算都是无符号的计算,就是都是正数的计算。
;加法的指令是add,减法的是sub,乘法的是mul,除法的是div
;这里主要是要注意寄存器的容量。
;以前说过,比如al是单字节,最多为十六进制的FF,即最多为255,超过就不行。
;所以,我们给寄存器赋值时要考虑一下,使用的寄存器的最大值
;这里基本上都是使用eax或ebx之类的,是32位,即最大值可以十六进制的FFFFFFFF,也就是4294967295,所以很难超过这个值,一般不会出错
;最后一个是除法,你看这一句 mov ebx,11
;意思是除数是在ebx里面,而ebx是32位,根据除法的原则,除数是32位,那被除数应该是64位,被除数是除数的两倍容量,因为必须保证被除数大于除数
;当然,如果除数是16位,那么被除数就应该是32位,以此类推。
;好吧,如果你搞不清楚哪个是被除数,哪个是除数,这里的4294967295/11,4294967295就是被除数,11就是除数。
;你观察一下,4294967295是十进制值,转换为十六进制,那就是FFFFFFFF,每个字节最大的值是FF,这里是8个F,也就是只能装4个字节,而eax就是4个字节。
;这时候,被除数的低字节是eax,高字节是edx,简单地说,就是把edx和eax拼起来,可以装下更大的值。把edx和eax拼起来是系统规定,不能说我要把ebx和eax拼起来也行。
;假设被除数是4294967296,比eax可以装的最大值大1,转换成十六进制就是100000000,它比FFFFFFFF就多了1位,用eax就装不下了。
;我们可以试试,强行把4294967296赋值给eax,看会不会出错。
;那解决的办法是把用2个寄存器来装。
;这里,我们又要复习一下原来字节的知识,不然又被绕糊涂了。
;我们常说的二进制与十六进制,这个东西就是用于计算机使用的。
;一个字节是八位的,在二进制中,每位要么0,要么1.就是物理上的高电平与低电平,假设都是1,则一个字节的值是11111111,你可以数数,就有8个1了,这是一个字节能表达的最大值
;那一个字节能表达多少个值呢。你可以从00000000到11111111,挨个算
;00000000,00000001,00000011,00000111,00001111.....10000000,10000001......11111111
;8位的情况下,所有的组合,其实就是256个
;这样的表达很要命,后来找到一种更好的表达,就是十六进制
;它就是0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F,代表的是0到15,总共是16个
;它的组合就是0,1,2,3....9,A,B,C,D,E,F,10,11,....A0,A1,A2....AA,AB,AC...FD,FE,FF,总数也是256个
;你留意一下,十六进制的FF,就是二进制的11111111,就是十进制的255,也就是一个字节能表达的最大值
;回到代码上来,你会发现4294967296转换成十六进制是100000000,但是1个字节的最大值是FF,那eax是4个字节,那最大是FFFFFFFF,只能塞进8个F,而这个100000000有9个值,塞不进去了
;那这个时候就把低位的塞到eax里去,这里低位的就是8个0,所以mov eax,0
;把高位的,就是100000000里面的1,塞进edx里去,就有前面的edx,1
;要是乘法的结果,超出了这个值,怎么办呢。这个就是反过来,edx里放结果的高位值,eax里面放结果的低位值。
;这个涉及到标志位,又有新知识,下次专门讲一下操作了,先学简单的,慢慢地进步。
;当然,大部分的时候,用不上这么大的值,基本上用eax或ebx之类的就可以。
;仔细想想,我想你应该能明白了。
;当然,并不是只能用寄存器来进行计算,也可以用内存来计算,原理类似,只是表达的不同,下次专门讲一讲。
;关于如何用内存来计算,可以查看本博客有关的其它文章,也有详细的示例说明。
;以下是资源Rc文件内容
#include "resource.h"
#define ICO_MAIN 1000 //图标
#define IDB01 101
#define IDB02 102
#define IDB03 103
#define IDB04 104
#define IDB05 105
ICO_MAIN ICON "Main.ico"
MyDialog DIALOGEX 10, 10, 110, 130
STYLE WS_SYSMENU|WS_CAPTION|WS_MINIMIZEBOX|WS_BORDER|DS_CENTER|DS_SETFONT|DS_3DLOOK
CAPTION "我是对话框程序"
FONT 12, "方正姚体"
BEGIN
PUSHBUTTON "计算 11+22 ",IDB01,10,20,90,12
PUSHBUTTON "计算 22-11 ",IDB02,10,40,90,12
PUSHBUTTON "计算 11*22 ",IDB03,10,60,90,12
PUSHBUTTON "计算 4294967295/11 ",IDB04,10,80,90,12
PUSHBUTTON "计算 4294967296/11 ",IDB05,10,100,90,12
END