Basm也比较方便

本文介绍了一位东欧开发者使用BASM(汇编语言)为Delphi编写的应用程序,展示了如何利用BASM进行Windows程序开发,特别是针对Delphi5环境下的实践技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

东欧牛人“圣父”的hxdef(黑客守卫者)重新钩起了我对Delphi的兴趣,“圣父”基乎是全用Basm写成了hxdef。

天天都用C/C++,Object Pascal感觉自己怎么也用不熟,昨晚看了一下Object Pascal的Inline ASM,主要是堆栈的安排以及Register和Pascal调用与C的Cdecl及API的Stdcall不太一样,什么引用型变量,指针等在汇编中的内存结构与C中的差不多,对象类型的Self指针(C中叫This指针)都是通过ecx传递,但在Basm中调用类类型的成员函数以及虚拟成员函数都要比C++的Inline调用对象的成员函数和虚拟成员函数要方便很多。

使用Delphi Basm来写Win32程序就不需要考虑引入什么库,uses一下单元文件就可以了,而且Delphi Inline ASM中可以使用db,dd之类的宏,可以方便的将数据与代码混合在一起,虽然在代码段,但只需要将变量占用内存属性改一下,它们就可以被读写,就像它们被定义在数据段一样.

如果只想在Delphi中使用Basm那么就应该将所有的块语句都用asm...end来表示,而不是begin...end.

最主要的还是对Intel x86汇编的掌握,以及编译器从高级语言生成汇编代码的规则的理解,最后用一段巨菜的代码练习一下Basm,基本上是没有Pascal代码的纯Basm汇编。程序使用Delphi5编译运行通过,Delphi7编译不通过很多常量不能用,看来如果是用纯Basm劝你还是用Delphi5,这也是很多牛人还在用Delphi5的原因吧。

//File:Basm.dpr

program Basm;
{$APPTYPE GUI}
uses
  Windows,
  Messages;

var
    strClsName:string='BasmWndCls';
    strCaption:string='BasmDemo';
    strText:string='Basm还真方便,难道不是吗?';

function WndProc(hWnd:HWND;uMsg:UINT;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall ;
var
    ps:PAINTSTRUCT;
    hWndDC:HDC;
asm
    mov eax,uMsg
    cmp eax,WM_PAINT
    je  @LWm_Paint
    cmp eax,WM_DESTROY
    je  @LWm_Destroy
    cmp eax,WM_CLOSE
    je  @LWm_Close

    //其它的信息做缺省处理
    jmp @LDefault
   
@LWm_Paint:
    lea eax,ps
    push eax//for endpaint

    //BeginPaint(hWnd,&ps);
    push eax
    push hWnd
    call BeginPaint
    mov hWndDC,eax

    push DT_CENTER or DT_VCENTER or DT_SINGLELINE
    lea eax,ps.rcPaint
    push eax
    push -1

//Delphi BASM中可以这样做类型转换,真方便,string类型的前两个DWORD,
//全别是长度和引用计数,从第9个byte开始才是零终止的字符串,用PChar[]
//编译器会自动引用从9字节开始的地址
    push PChar[strText]
    push hWndDC
    call DrawText

    //EndPaint(hWnd,&ps);
    push hWnd
    call EndPaint
    jmp @LQuit
@LWm_Close:
    push hWnd
    call DestroyWindow
    jmp @LQuit
@LWm_Destroy:
    push 0
    call PostQuitMessage
    jmp @LQuit
@LDefault:
    push lParam
    push wParam
    push uMsg
    push hWnd
    call DefWindowProc
    jmp @@1
@LQuit:
    xor eax,eax
@@1:
end;


function WinMain(hInstance,PrevInst:HINST;lpszCmdLine:LPTSTR;nShow:DWORD):integer;stdcall ;
var
    WndCls:WNDCLASSEX;
    MsgV:MSG;
asm
    //memset(&MsgV,0,sizeof(MsgV));
    lea edi,MsgV
    mov ecx,type MsgV
    xor eax,eax
    rep stosb

    //memset(&WndCls,0,sizeof(WndCls));
    lea edi,WndCls
    mov ecx,type WNDCLASSEX
    push ecx
    rep stosb
    pop WndCls.cbSize

    mov WndCls.style, CS_VREDRAW or CS_HREDRAW
    mov WndCls.lpfnWndProc,offset WndProc
    mov eax,hInstance
    mov WndCls.hInstance,eax

    //LoadIcon(NULL,IDI_APPLICATION);
    xor eax,eax
    push IDI_APPLICATION
    push eax
    call LoadIcon
    mov WndCls.hIcon,eax
    mov WndCls.hIconSm,eax

    //LoadCursor(NULL,IDC_ARROW);
    xor eax,eax
    push IDC_ARROW
    push eax
    call LoadCursor
    mov WndCls.hCursor,eax

    mov WndCls.hbrBackground,COLOR_WINDOW+1
    push PChar[strClsName]
    pop WndCls.lpszClassName

    //RegisterClass(&WndCls);
    lea eax,WndCls
    push eax
    call RegisterClassEx
    test eax,eax
    je @LQuit


    //CreateWindowEx(NULL,strClsname,strCaption,WS_OVERLAPPEDWINDOW,
    //CW_USEDEFAULT,CW_USEDEFAULT,
    //CW_USEDEFAULT,CW_USEDEFAULT,
    //NULL,NULL,
    //hInstance,
    //NULL);
    xor eax,eax
    push eax
    push hInstance
    push eax
    push eax
    mov eax,CW_USEDEFAULT
    push eax
    push eax
    push eax
    push eax
    push WS_OVERLAPPEDWINDOW
    push PChar[strCaption]
    push PChar[strClsName]
    push 0
    call CreateWindowEx
    test eax,eax
    je @LQuit

    //ShowWindow(hWnd,nShow);
    //UpdateWindow(hWnd);
    push eax
    push nShow
    push eax
    call ShowWindow
    call UpdateWindow
    //while(GetMessage(&MsgV,NULL,0,0)
@LMsgLoop:
    xor eax,eax
    push eax
    push eax
    push eax
    lea eax,MsgV
    push eax
    call GetMessage
    test eax,eax
    je @LQuit

    //TranslageMessage(&MsgV);
    //DispatchMessage(&MsgV);
    lea eax,MsgV
    push eax
    push eax
    call TranslateMessage
    call DispatchMessage
    jmp @LMsgLoop
@LQuit:
end;

asm
    push CmdShow
    push CmdLine
    push 0
    push MainInstance
    call WinMain
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值