NASM - The Netwide Assembler
Related Projects => NASMX => Topic started by: avcaballero on February 22, 2015, 03:45:16 PM
-
Hello. I'm updating my win32 tuto. It has full samples on masm and fasm and I wanted to upgrading it to nasmx. It was at 90% when I realized that I was making it with v1.2 :( Never mind, let's go for v1.4.
The present message is due to that I have found an error, probably loading a dll, that doesn't allow me to progress in the SQLite example.
mainWN02.asm.
This program reads some functions from dllWN01.dll. It worked ok in v1.2, but don't in v1.4 (I have attached both, same code). In fact, I think that the subroutines in the dll works akay, and, for demonstrate that, I have incorporated a messagebox showing the calculated value in ASCIIZ. The v12 mainWN02.v12.exe works fine as you can see.
bmpWN02b.asm
I think there's something strange in BITMAPINFOHEADER structure?, because I had to change manually several things to making the program work (in v1.2 it worked fine without those changes). This is a bmp reasizable viewer program loaded into memory (just for 1 bmp file, I will upgrade it when I have time). I have used a tricky to get the addr of a local variable (is there anything available already for it?):
mov eax, ebp
sub eax, .dwBytesRead ; Truqui para el ADDR de dwBytesRead
There are some other problems/issues that I have encountered in v1.2. that I will check for v1.4:
* The buttons2 example doesn't change the boxing globe cursor when the cursor get off from the politician button. I cannot use UDC_HyperLink in my rc file if I want the DialogBoxParam that calls this dialog box work. Everything else is working ok: double image buttons, etc.
* The SQLite example doesn't read properly the units food. I believe that some problem in local variables gestion, I will check in v1.4 that I think has changed that.
* Is it possible to define local structure variables?
* Is it possible to define a local variable similar to that?
locals
local myVar[40], dword
endlocals
* Is it possible to do something like this?
if eax, <=, 30, &&, eax, >= 5, [and so on]
[...]
* Is it possible to make my own subroutines?
myProc:
push ebp
mov ebp, esp
sub esp, 4*5 ; Space for 5 dwords
[...]
mov esp, ebp
pop ebp
I have used it, but I think that, at least, in v12 it is not possible to execute an "invoke" command inside, even if I push and call manually.
I keep on working on that but I go a bit slow because I just have a bit of time at weekends, so if anyone want to help... :)would be welcome.
Regards.
-
Hello, I think that I already know where is the problem in the mainWN02.asm
mov esp, ebp ; ** This is not in the resulting code **
endproc
Regards
-
Hey, Alfonso!
I'll answer some of the simpler questions first and get back to you later regarding your source code once I get some free time and played around with it a bit.
Hello. I'm updating my win32 tuto. It has full samples on masm and fasm and I wanted to upgrading it to nasmx. It was at 90% when I realized that I was making it with v1.2 :( Never mind, let's go for v1.4.
Thank you for doing this. Your tutorials are excellent and the Spanish translations are very beneficial. And yes, please use v1.4 for all your examples.
I think there's something strange in BITMAPINFOHEADER structure?, because I had to change manually several things to making the program work (in v1.2 it worked fine without those changes).
The big change with 1.4 was a correction of structure alignment and size which was not 100% correct in previous versions. Specifically, now the answer to these questions:
* Is it possible to define local structure variables?
* Is it possible to define a local variable similar to that?
locals
local myVar[40], dword ; <-- CHANGE TO THIS: local myVar, dword, 40
; USE SAME TECHNIQUE FOR STRUCTS
endlocals
is yes - we officially and correctly support local and global arrays of data sets ( including structures ).
I have used a tricky to get the addr of a local variable (is there anything available already for it?):
mov eax, ebp
sub eax, .dwBytesRead ; Truqui para el ADDR de dwBytesRead
That is exactly how to do it. The reason you need to dot prepended to the name has to do with both scoping and name mangling which occurs when complying with the calling convention in use. Internally, all local variables you create are labelled as YOUR_FUNC_NAME.YOUR_LOCAL_VAR_NAME which subsequently allows you to re-use the same variable name in multiple functions within the same source file just like C - something not possible when using regular labels. It is also the reason why you should not define a label within a PROC without a dot prepended to it. Otherwise, you may encounter issues later on in your code when you attempt to get a local var. In a nutshell - use the dot!
See this page for further info: http://www.nasm.us/xdoc/2.11.08/html/nasmdoc3.html#section-3.9 (http://www.nasm.us/xdoc/2.11.08/html/nasmdoc3.html#section-3.9)
* Is it possible to do something like this?
if eax, <=, 30, &&, eax, >= 5, [and so on]
[...]
Unfortunately, the answer is no. Although our macro set is quite powerful in allowing you to make use of constructs such as IF, WHILE, REPEAT, CONTINUE, BREAK, etc, we haven't implemented multiple-expression control statements. It is a good suggestion and perhaps may appear in a future release as I can see value in that.
* Is it possible to make my own subroutines?
myProc:
push ebp
mov ebp, esp
sub esp, 4*5 ; Space for 5 dwords
[...]
mov esp, ebp
pop ebp
I have used it, but I think that, at least, in v12 it is not possible to execute an "invoke" command inside, even if I push and call manually.
You can have Nasm procedures and NASMX procedures within the same source file but you can't use most NASMX macros outside of a NASMX PROC/ENDPROC pair. The reason has to do with calling conventions, stack, alignment, and how we use Nasm to set it all up for you.
-
OK. Found your problem in mainWN02.asm:
push dword [vdSuma2]
push dword [vdSuma1]
call dword [ptrFuncName]
as well as:
push szContent
push ptrdiff_t [argv(.hwnd)]
call dword [ptrProcName]
are both missing "add esp, 8" after the call!
Remember that if you are calling the functions directly ( eg: not using NASMX invoke macro ) you are also responsible for stack management. I'm sure that one probably just slipped your mind.
And no, you don't need to add the line "mov esp, ebp" in your source code prior to ENDPROC. I've verified that this is correctly handled by NASMX.
The program now works fine for me after this fix.
-
Ok, you are right, I was wrong because in v1.2 semeed not be necessary to recover the stack after the call, just checking for the code to work and missed recover the stack ???. There is no need to recover esp before "endproc" because there are no local variables.
Regarding bmpWN02, according to the unassembly from OllyDbg, there are some differences between the code compiled with v1.2 and v1.4 for GetBMPSize:
CPU Disasm
Address Hex dump Command Comments
004010EE /$ 55 PUSH EBP
004010EF |. 89E5 MOV EBP,ESP
004010F1 |. 895D FC MOV DWORD PTR SS:[LOCAL.1],EBX
004010F4 |. 8975 F8 MOV DWORD PTR SS:[LOCAL.2],ESI
004010F7 |. 83EC 08 SUB ESP,8
004010FA |. 8B1D 34214000 MOV EBX,DWORD PTR DS:[402134]
00401100 |. B8 0E000000 MOV EAX,0E [b]; Look at this for example, in v1.4 is 10[/b]
00401105 |. 01D8 ADD EAX,EBX
00401107 |. A3 38214000 MOV DWORD PTR DS:[402138],EAX
0040110C |. 89C6 MOV ESI,EAX
0040110E |. 8B43 0A MOV EAX,DWORD PTR DS:[EBX+0A]
00401111 |. 01D8 ADD EAX,EBX
00401113 |. A3 3C214000 MOV DWORD PTR DS:[40213C],EAX
00401118 |. 31C0 XOR EAX,EAX
0040111A |. 31DB XOR EBX,EBX
0040111C |. 833E 0C CMP DWORD PTR DS:[ESI],0C
0040111F |. 75 0A JNE SHORT 0040112B
00401121 |. 66:8B46 04 MOV AX,WORD PTR DS:[ESI+4]
00401125 |. 66:8B5E 06 MOV BX,WORD PTR DS:[ESI+6]
00401129 |. EB 0D JMP SHORT 00401138
0040112B |> 8B46 04 MOV EAX,DWORD PTR DS:[ESI+4]
0040112E |. 8B5E 08 MOV EBX,DWORD PTR DS:[ESI+8]
00401131 |. 83FB 01 CMP EBX,1
00401134 |. 7F 02 JG SHORT 00401138
00401136 |. F7DB NEG EBX
00401138 |> A3 48214000 MOV DWORD PTR DS:[402148],EAX
0040113D |. 891D 4C214000 MOV DWORD PTR DS:[40214C],EBX
00401143 |. 83C4 08 ADD ESP,8
00401146 |. 5E POP ESI
00401147 |. 5B POP EBX
00401148 |. 89EC MOV ESP,EBP
0040114A |. 5D POP EBP
0040114B \. C3 RETN
CPU Disasm
Address Hex dump Command Comments
004010EA /$ 55 PUSH EBP
004010EB |. 53 PUSH EBX
004010EC |. 56 PUSH ESI
004010ED |. 8B1D 34214000 MOV EBX,DWORD PTR DS:[402134]
004010F3 |. B8 10000000 MOV EAX,10 [b]; Look at this for example, in v1.2 is 0E[/b]
004010F8 |. 01D8 ADD EAX,EBX
004010FA |. A3 38214000 MOV DWORD PTR DS:[402138],EAX
004010FF |. 89C6 MOV ESI,EAX
00401101 |. 8B43 0C MOV EAX,DWORD PTR DS:[EBX+0C]
00401104 |. 01D8 ADD EAX,EBX
00401106 |. A3 3C214000 MOV DWORD PTR DS:[40213C],EAX
0040110B |. 31C0 XOR EAX,EAX
0040110D |. 31DB XOR EBX,EBX
0040110F |. 833E 0C CMP DWORD PTR DS:[ESI],0C
00401112 |. 75 0A JNE SHORT 0040111E
00401114 |. 66:8B46 04 MOV AX,WORD PTR DS:[ESI+4]
00401118 |. 66:8B5E 06 MOV BX,WORD PTR DS:[ESI+6]
0040111C |. EB 0D JMP SHORT 0040112B
0040111E |> 8B46 04 MOV EAX,DWORD PTR DS:[ESI+4]
00401121 |. 8B5E 08 MOV EBX,DWORD PTR DS:[ESI+8]
00401124 |. 83FB 01 CMP EBX,1
00401127 |. 7F 02 JG SHORT 0040112B
00401129 |. F7DB NEG EBX
0040112B |> A3 48214000 MOV DWORD PTR DS:[402148],EAX
00401130 |. 891D 4C214000 MOV DWORD PTR DS:[40214C],EBX
00401136 |. 5E POP ESI
00401137 |. 5B POP EBX
00401138 |. 5D POP EBP
00401139 \. C3 RETN
Thank you for your time, Rob. It seems to be scarced for all of us :)
The source code for bmpWN02, same for v1.2 and v1.4. I wanted to attach a zip file, but it seems that it is not possible on a sended post.
; ----------------------------------------------------------------------------
; - TITULO : Ejemplo de load-bmp en ventana W-NASMX v1.4 -
; ----- -----
; - AUTOR : Alfonso Víctor Caballero Hurtado -
; ----- -----
; - VERSION : 1.0 -
; ----- -----
; - (c) 2015. Abre los Ojos al Ensamblador -
; ----------------------------------------------------------------------------
%include '..\..\windemos.inc'
cdXPos EQU 128
cdYPos EQU 128
cdXSize EQU 320
cdYSize EQU 200
cdColFondo EQU COLOR_BTNFACE + 1
cdVIcono EQU IDI_APPLICATION
cdVCursor EQU IDC_ARROW
cdVBarTipo EQU NULL
cdVBtnTipo EQU WS_VISIBLE+WS_OVERLAPPEDWINDOW ; Botones de minimizar, maximizar y cerrar
DIB_RGB_COLORS equ 0
entry Entrada
[section .bss]
hInstance: reserve(ptrdiff_t) 1
CommandLine: reserve(ptrdiff_t) 1
hWnd: reserve(ptrdiff_t) 1
hdc: reserve(ptrdiff_t) 1
hBitmap: reserve(ptrdiff_t) 1
hMemDC: reserve(ptrdiff_t) 1
hMemory: reserve(ptrdiff_t) 1
pBMPbuf: reserve(ptrdiff_t) 1
pBMPi: reserve(ptrdiff_t) 1
pBMPBits: reserve(ptrdiff_t) 1
vdXCliente: reserve(ptrdiff_t) 1
vdYCliente: reserve(ptrdiff_t) 1
vdXBMP: reserve(ptrdiff_t) 1
vdYBMP: reserve(ptrdiff_t) 1
vbRedimens: reserve(ptrdiff_t) 1
; dwHighSize: reserve(ptrdiff_t) 1
; dwBytesRead: reserve(ptrdiff_t) 1
[section .data]
NombreClase: declare(NASMX_TCHAR) NASMX_TEXT("SimpleWinClass"), 0
MsgCabecera: declare(NASMX_TCHAR) NASMX_TEXT("Ejemplo de load-bmp en ventana (NasmX)"), 0
MsgError: declare(NASMX_TCHAR) NASMX_TEXT("Carga inicial fallida."),0
Cantload: declare(NASMX_TCHAR) NASMX_TEXT("No se puede cargar el BMP-fichero"),0
vsBMPFilePath: declare(NASMX_TCHAR) NASMX_TEXT("Ejemplo.bmp"),0
NASMX_ISTRUC rect, RECT
NASMX_IENDSTRUC
NASMX_ISTRUC ps, PAINTSTRUCT
NASMX_IENDSTRUC
NASMX_ISTRUC wc, WNDCLASSEX
NASMX_AT cbSize, WNDCLASSEX_size
NASMX_AT style, CS_VREDRAW + CS_HREDRAW
NASMX_AT lpfnWndProc, NULL
NASMX_AT cbClsExtra, NULL
NASMX_AT cbWndExtra, NULL
NASMX_AT hInstance, NULL
NASMX_AT hIcon, NULL
NASMX_AT hCursor, NULL
NASMX_AT hbrBackground, COLOR_BTNFACE + 1
NASMX_AT lpszMenuName, NULL
NASMX_AT lpszClassName, NULL
NASMX_AT hIconSm, NULL
NASMX_IENDSTRUC
NASMX_ISTRUC message, MSG
NASMX_AT hwnd, NULL
NASMX_AT message, NULL
NASMX_AT wParam, NULL
NASMX_AT lParam, NULL
NASMX_AT time, NULL
NASMX_ISTRUC pt, POINT
NASMX_AT x, NULL
NASMX_AT y, NULL
NASMX_IENDSTRUC
NASMX_IENDSTRUC
[section .text]
proc LoadBMP2Mem, dword pstrFileName
; Propósito: Cargamos un BMP en memoria dinámica
; Entrada : pstrFileName: la ruta del BMP-fichero a cargar
; Salida : EAX: El puntero al bmp cargado en memoria
; Destruye : Ninguna
uses ebx
locals
local bSuccess,dword ; Local2= ebp-4*2
local dwFileSize,dword ; Local3= ebp-4*3
local dwHighSize,dword
local dwBytesRead,dword
local hFile,dword ; Local4= ebp-4*4
local lpBMPbuf,dword ; Local5= ebp-4*5
endlocals
invoke CreateFileA, dword [argv(.pstrFileName)], GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0 ; Abrimos fichero para lectura
mov dword [var(.hFile)], EAX ; Guardamos el file-handle
cmp EAX, INVALID_HANDLE_VALUE ; Comprobamos si ha ido bien
je .LBM_Fin_Error
mov eax, ebp
sub eax, .dwHighSize ; Truqui para el ADDR de dwHighSize
invoke GetFileSize, dword [var(.hFile)], eax ; Obtenemos el tamaño del BMP-fichero
mov dword [var(.dwFileSize)], eax ; y lo guardamos
or dword [var(.dwHighSize)], 0 ; Comprobamos si hubo éxito, dwHighSize no NULL
jz .Next1
invoke CloseHandle, dword [var(.hFile)]
jmp .LBM_Fin_Error
.Next1:
invoke GlobalAlloc,GMEM_MOVEABLE + GMEM_ZEROINIT, dword [var(.dwFileSize)] ; Reservamos memoria para dwFileSize
mov dword [hMemory], EAX ; Guardamos la memoria-handle
invoke GlobalLock, dword [hMemory] ; Bloquea la memoria reservada
mov dword [var(.lpBMPbuf)], EAX ; Y devuelve un puntero al primer byte: BITMAPFILEHEADER
mov EBX, EAX ; Lo guardamos también en EBX
or dword [var(.lpBMPbuf)], 0 ; Si falló
jne .Next2
invoke CloseHandle, dword [var(.hFile)] ; cerramos el bmp-fichero y salimos
jmp .LBM_Fin_Error
.Next2:
mov eax, ebp
sub eax, .dwBytesRead ; Truqui para el ADDR de dwBytesRead
invoke ReadFile, dword [var(.hFile)], dword [var(.lpBMPbuf)], dword [var(.dwFileSize)], eax, 0
; hFile:Handle del fichero a leer, lpBMPbuf:Dirección del búfer que recibirá los datos,
; dwFileSize:número de bytes a leer, dwBytesRead:número de bytes leídos, 0:lpOverlapped
mov dword [var(.bSuccess)], EAX ; Si hubo éxito devuelve un valor noCero
invoke CloseHandle, dword [var(.hFile)] ; Cerramos el bmp-fichero
mov EAX, dword [var(.dwBytesRead)] ; Los bytes efectivamente leídos
mov CX, word [BITMAPFILEHEADER.bfType+ebx] ; Obtenemos el tipo de fichero de la cabecera: (2bytes) BM
xchg cl, ch ; ¿Es necesario?
mov EDX, dword [BITMAPFILEHEADER.bfSize+EBX] ; Tamaño en bytes del bmp
; Comprobamos que es un fichero correcto
or dword [var(.bSuccess)], 0
je .Next3
cmp eax, dword [var(.dwFileSize)]
jne .Next3
cmp cx, "MB"
jne .Next3
cmp edx, dword [var(.dwFileSize)]
jne .Next3
jmp .Next4
.Next3:
invoke GlobalUnlock, dword [var(.lpBMPbuf)] ; Desbloqueamos la memoria reservada
invoke GlobalFree, dword [hMemory] ; y la liberamos
.Next4:
mov eax, dword [var(.lpBMPbuf)]
jmp .LBM_Fin
.LBM_Fin_Error:
mov eax, 0
.LBM_Fin:
endproc
proc GetBMPSize
; Propósito: Obtiene el tamaño del bmp así como los punteros
; Entrada : pBMPbuf: puntero al bmp-búfer
; Salida : pBMPi: puntero a la bmp-información, pBMPBits: puntero al vigente BMP pixel bits
; vdXBMP: anchura del bmp, vdYBMP: altura del BMP
; Destruye : EAX
uses ebx, esi
locals none
; Obtiene los punteros a la estructura de información Get pointers to the info structure & the bits
MOV EBX, dword [pBMPbuf] ; Guardamos en EBX el puntero a la cabecera del bmp en el búfer
MOV EAX, BITMAPFILEHEADER_size ; Si sumamos el tamaño de la cabecera
ADD EAX, EBX ; con la dirección de ésta,
MOV dword [pBMPi], EAX ; Obtenemos el puntero a la bmp-información
MOV ESI, EAX ; Lo guardamos en ESI también
MOV EAX, [EBX+BITMAPFILEHEADER.bfOffBits]; Recogemos de la cabecera la dirección de los bits
ADD EAX, EBX ; Sumándole la dirección de la cabecera
MOV dword [pBMPBits], EAX ; Obtenemos un puntero al vigente BMP pixel bits
XOR EAX, EAX ; Lo inicializamos primero
XOR EBX, EBX ; para asegurarnos de borrar la parte superior
; Obtenemos la anchura y altura del BMP
CMP dword [ESI+BITMAPINFOHEADER.biSize], BITMAPCOREHEADER_size ; Ancho y alto son WORDs
JNE .L_SBMPS_Sino
MOV AX, word [ESI+BITMAPCOREHEADER.bcWidth] ; Anchura del BMP
MOV BX, word [ESI+BITMAPCOREHEADER.bcHeight] ; Altura del BMP
JMP .L_SBMPS_Exit
.L_SBMPS_Sino: ; Ancho y alto son DWORDs
MOV EAX, dword [ESI+BITMAPINFOHEADER.biWidth] ; Anchura del BMP
MOV EBX, dword [ESI+BITMAPINFOHEADER.biHeight] ; Altura del BMP
CMP EBX, 1
JG .L_SBMPS_Exit
NEG EBX ; Obtenemos el valor absoluto
.L_SBMPS_Exit: ; Ancho y alto son DWORDs
MOV dword [vdXBMP], EAX
MOV dword [vdYBMP], EBX
endproc
proc WndProc, ptrdiff_t hwnd, dword uMsg, size_t wParam, size_t lParam
; Propósito: Procesa los mensajes provenientes de las ventanas
; Entrada : hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
; Salida : Ninguna
; Destruye : Ninguna
locals none
mov eax, ptrdiff_t [argv(.uMsg)]
cmp eax, WM_PAINT
jz .wmPaint
cmp eax, WM_CREATE
jz .wmCreate
cmp eax, WM_SIZE
jz .wmSize
cmp eax, WM_DESTROY
jz .wmDestroy
.wmDefault:
invoke DefWindowProcA, ptrdiff_t [argv(.hwnd)], ptrdiff_t [argv(.uMsg)], ptrdiff_t [argv(.wParam)], ptrdiff_t [argv(.lParam)]
jmp .wmFin
.wmSize:
; Recogemos en las variables la anchura y altura de la ventana
mov byte [vbRedimens], 1 ; avch: este flag tampoco es necesario en MASM
MOV EAX, ptrdiff_t [argv(.lParam)]
AND EAX, 0FFFFh ; Nos quedamos con el word bajo
MOV [vdXCliente], EAX
MOV EAX, ptrdiff_t [argv(.lParam)]
SHR EAX, 16 ; Nos quedamos con el word alto: 2^16=10000h
MOV [vdYCliente], EAX
jmp .wmPaint
; avch. Atención, ESTO ES IMPORTANTE. Ha sido necesario redireccionar a "wm_paint" porque cuando se
; redimensiona la ventana cliente a mayor, se produce un suceso "wm_paint", pero cuando se redimensionaba
; a menor, no. Por lo tanto se escalaba el bmp sólo cuando se agrandaba, no cuando se achicaba.
; Sin embargo, en MASM esto no era necesario ???
jmp .wmFin
.wmCreate:
invoke LoadBMP2Mem, vsBMPFilePath ; Carga en memoria el fichero bmp
mov dword [pBMPbuf], eax ; Devuelve el puntero en memoria para el bitmapbuffer
or dword [pBMPbuf], 0 ; Si no se pudo cargar en memoria
jnz .Next2
invoke MessageBox, ptrdiff_t [argv(.hwnd)], Cantload, MsgCabecera, 0
mov EAX, MB_ICONEXCLAMATION + MB_OK
jmp .wmFin
.Next2:
; invoke InvalidateRect, [hwnd], NULL, TRUE ;Invalidate client area for later update
call GetBMPSize ; Obtiene el tamaño del bmp y los punteros pBMPBits y pBMPi
jmp .wmFin
.wmPaint:
invoke BeginPaint,ptrdiff_t [argv(.hwnd)],ps
mov dword [hdc],eax
or dword [pBMPbuf], 0
jz .Next3
invoke SetStretchBltMode, [hdc], COLORONCOLOR
invoke StretchDIBits, [hdc], 0,0, [vdXCliente], [vdYCliente], 0,0,[vdXBMP],[vdYBMP], \
[pBMPBits], [pBMPi], DIB_RGB_COLORS, SRCCOPY
or byte [vbRedimens], 0 ; avch: Ninguna de estas líneas para invalidateRect son necesarias en MASM
jz .Next3
invoke InvalidateRect, ptrdiff_t [argv(.hwnd)], NULL, TRUE ; Invalidate client area for later update
mov byte [vbRedimens], 0
.Next3:
invoke EndPaint,ptrdiff_t [argv(.hwnd)],ps
jmp .wmFin
.wmDestroy:
cmp dword [pBMPbuf], 0
jz .Next1
invoke GlobalUnlock, [pBMPbuf] ; Desbloquea la memoria asignada
invoke GlobalFree, [hMemory] ; Libera la memoria asignada
.Next1:
invoke PostQuitMessage,0
.wmFin:
endproc
proc WinMain, ptrdiff_t hinst, ptrdiff_t hpinst, ptrdiff_t cmdln, dword dwshow
locals none
invoke LoadIcon, NULL, IDI_APPLICATION
mov __CX, wc
mov ptrdiff_t [__CX + WNDCLASSEX.hIcon], __AX
mov ptrdiff_t [__CX + WNDCLASSEX.hIconSm], __AX
mov ptrdiff_t [__CX + WNDCLASSEX.lpfnWndProc], WndProc
mov ptrdiff_t [__CX + WNDCLASSEX.lpszClassName], NombreClase
mov __AX, ptrdiff_t [argv(.hinst)]
mov ptrdiff_t [__CX + WNDCLASSEX.hInstance], __AX
invoke RegisterClassEx, __CX
invoke CreateWindowEx, cdVBarTipo, NombreClase, MsgCabecera, \
cdVBtnTipo,\
cdXPos, cdYPos, cdXSize, cdYSize, NULL, NULL, \
ptrdiff_t [wc + WNDCLASSEX.hInstance], NULL
mov ptrdiff_t [hWnd], __AX
invoke ShowWindow, hWnd, dword [argv(.dwshow)]
invoke UpdateWindow, hWnd
.msgloop:
invoke GetMessage, message, NULL, NULL, NULL
cmp eax, dword 0
je .exit
invoke TranslateMessage, message
invoke DispatchMessage, message
jmp .msgloop
.exit:
mov eax, dword [message + MSG.wParam]
endproc
proc Entrada, ptrdiff_t argcount, ptrdiff_t cmdline
locals none
invoke GetModuleHandle, NULL
mov ptrdiff_t [hInstance], __AX
invoke WinMain, hInstance, NULL, NULL, SW_SHOWNORMAL
invoke ExitProcess, NULL
endproc
-
Only 2000 chars allowed , attach zip
* bmpWN02.asm. This is the same and "correct" code for v1.2 and v1.4. I have included the v1.2 exe file and v1.4. I include the unassembly source from OllyDbg for both. You can see, for example, that in v1.2 is "MOV EAX, 0E" and in v1.4 is "MOV EAX, 10".
* bmpWN02b.asm. With this code v1.4 works fine. You can compare with the previous one with a comparer text tool.
Sorry for inconveniences and thanks for the time
-
* bmpWN02.asm. This is the same and "correct" code for v1.2 and v1.4. I have included the v1.2 exe file and v1.4. I include the unassembly source from OllyDbg for both. You can see, for example, that in v1.2 is "MOV EAX, 0E" and in v1.4 is "MOV EAX, 10".
The problem is that in your personal windemos.inc file you probably have the definition of BITMAPFILEHEADER without alignment packing instructions. If you look in /nasmx/inc/win32/windows.inc you will see the following:
NASMX_PRAGMA PACK, PUSH, 2
NASMX_STRUC BITMAPFILEHEADER
NASMX_RESERVE bfType, short_t, 1
NASMX_RESERVE bfSize, int32_t, 1
NASMX_RESERVE bfReserved1, short_t, 1
NASMX_RESERVE bfReserved2, short_t, 1
NASMX_RESERVE bfOffBits, int32_t, 1
NASMX_ENDSTRUC
NASMX_PRAGMA PACK, POP
By default, without the pragma PACK, PUSH, 2 option, NASMX will align structure variables and size the structure according to the rules of natural alignment. The alignment for that structure would be 4 (DWORD) which would make the bfSize member at offset 4 thus increasing the size of the structure from 0x0E to 0x10.
However, for this specific structure Microsoft forces WORD alignment thus we have to comply with that. Subsequently, in NASMX, we enclose that structure with PACK 2 to do the same. The WORD alignment now puts bfSize at offset 2 and the size of the structure is now 0x0E. You'll simply need to update your own windemos.inc file similarly.
Had you used windows.inc you'd not have experienced this. That's the trade-off of rolling your own include file: speed of assembly time vs. compatibility. Trust me when I say I know the pain of pulling in all those headers and use a custom version myself. Having pre-compiled headers sure would make things much better.
-
Yes, you were right once again, now it works. Thank you for your time, Rob. Remind me that I owe you a beer ;D.
-
And I will say thank you for your efforts as well. I'd love to get together and share a few beers with you one day! :)
-
That's would be a pleasure. Don't believe that I'll be in the USA, but if you were in Spain sometime, it would be very nice to lower the foam a few beers with you. In fact, it would be nice to make an encounter of asm programmers... sometime... somewhere 8).
By the way, if you are interested, I attach a review of demo17 in a better code. The dib section is created in the "create" section, in such a way that in the Paint section you just need to calculate the floor data and bitblt it to the memory.
Regards
-
Now THAT is some beautiful Win32 NASMX assembly code right there. Neat, clean, and easy to understand. Good refactoring too. 8)
-
Hello, again.
Programs are working now. In the case of SQLite example I had to apply some trickies to get it working: I had to remove local variables in a subroutine and use global ones. And a few others. Never mind, it works. Let's say that you have a few friends and want to invite them to watch a football match and want to know how much will waste according the prize and units to consum for each of them saved in a SQLite DB. (program attached)
As for the loading dll example.
Remember that if you are calling the functions directly ( eg: not using NASMX invoke macro ) you are also responsible for stack management
It depends on the call convention:
- C. You have to balance the stack after the call.
- Pascal/stdcall. The subroutine called is in charge of balancing the stack before leaving. And we are in stdcall convention, are we? That's why I didn't balanced the stack after the call.
Seing at the dll code:
proto cdecl, addLongs, dword uno, dword dos
proto cdecl, MuestraMensaje, ptrdiff_t hWnd, dword content
I wondered what was such "cdecl" :), now I know: the declaration of call convention c-alike. So, looking at the dll dissasembly code there is no "RET 8", but just "RET". Dsssshh. Nearly.
Well, that's all for me. Thank you and up to another.