Pages: [1]
|
 |
|
Author
|
Topic: List of known MASM bugs (Read 17404 times)
|
jj2007
|
Japheth has already made an attempt to list the known MASM bugs. I think it would be extremely useful for beginners and seasoned programmers alike to find these bugs condensed in a list, maybe together with possible workarounds. I start with three simple examples: 1. The programmer can pass more arguments to a macro than needed. ML 6.14 and ML 9.0 issue only a warning (A4006:too many arguments in macro call), although the MessageBox will look a bit odd. JWasm recognises this as an error. include \masm32\include\masm32rt.inc
MBox MACRO text:REQ, title:REQ, style:REQ ; 3 arguments received invoke MessageBox, 0, text, title, style ENDM
.code MyTitle db "Ciao", 0
start: MBox 0, chr$("Message text, not title!"), addr MyTitle, MB_OK ; 4 arguments passed
exit
end start
2. Assembly gets slow, and ML may eventually freeze, for large buffers in the .data? section: .data? MySlowBuffer db 600000 dup(?) ; 0.6 mega: about 5 seconds
The workaround is a macro using the ORG directive (I owe this idea to drizz and MichaelW): (EDIT: link to drizz' post added - thanks Michael) include \masm32\include\masm32rt.inc
mkbuf MACRO var, BufLen LOCAL lbl .data? align 4 lbl LABEL byte ORG $+BufLen-1 db ? .data var dd lbl ;; define it in the data section .code ENDM
.data?
; MySlowBuffer db 600000 dup(?) ; 0.6 mega: about 5 seconds
.code
start: mkbuf MyBuffer, 100000000 ; one-hundred mega invoke MessageBox, 0, chr$("Done!"), chr$("Fat buffer:"), MB_OK exit
end start
3. The offset problem: Both versions of this code work for ml 6.14 and JWasm but ml 9.0 says error A2070:invalid instruction operands .data MyAccels ACCEL <FCONTROL or FVIRTKEY, VK_S, IdMenuSave> LastAccel ACCEL <FVIRTKEY, VK_ESCAPE, IdEscape> ... .code invoke CreateAcceleratorTable, addr MyAccels, 1+(offset LastAccel-MyAccels)/SIZEOF ACCEL
invoke CreateAcceleratorTable, addr MyAccels, 1+(dword ptr LastAccel-dword ptr MyAccels)/(SIZEOF ACCEL)
No workaround found yet, except sacrificing a register...
|
|
« Last Edit: December 04, 2008, 08:11:14 AM by jj2007 »
|
Logged
|
|
|
|
|
|
MichaelW
Global Moderator
Member
    
Gender: 
Posts: 5161
|
|
|
|
Logged
|
eschew obfuscation
|
|
|
jj2007
|
Calc PROTO,dPercent:DWORD ... Calc PROC, dPercent:DWORD
ret Calc ENDP
So what are you asking poor ml to do, Dave? What is the meaning of an "empty argument"? EDIT: Strangely enough, the empty argument is not the culprit - the commas after PROTO and PROC are being ignored. Since REC_PTRS EQU 12: INVOKE Calc, [esi+12] ; works like a charm ; INVOKE Calc,OFFSET [esi+12] ; does not work
What is the purpose of INVOKE Calc, OFFSET [esi+12] ? How does it differ from INVOKE Calc, [esi+12] ?
|
|
|
Logged
|
|
|
|
jj2007
|
Here is a minimalist demo of this behaviour: include \masm32\include\masm32rt.inc
.code MyWords dw 5678h, 1234h
start: mov esi, offset MyWords ; mov eax, OFFSET [esi] ; throws an error even in JWasm ; mov eax, OFFSET [esi+0] ; works with JWasm but ml 6+9 produce fatal error A1016: Internal Assembler Error mov eax, [esi+0] ; works with all versions, same result as JWasm
MsgBox 0, hex$(eax), chr$("Bug report:"), MB_OK exit
end start
MSDN is, as usual, incredibly verbose about the exact meaning of "offset": Microsoft Macro Assembler Reference operator OFFSET Returns the offset of expression.
|
|
« Last Edit: December 04, 2008, 12:30:09 PM by jj2007 »
|
Logged
|
|
|
|
Rockoon
|
The Masm workaround I use for the large BSS data is:
.data? COMM MyBigBuffer:dword:12345678
Which creates a buffer of 12345678 dwords. No messy macros, but probably doesnt work in other assemblers.
As for other bugs... I don't even know where to begin in regards to all the quirks of the macro language that have become 'features'
|
|
|
Logged
|
When C++ compilers can be coerced to emit rcl and rcr, I *might* consider using one.
|
|
|
japheth
Guest
|
MSDN is, as usual, incredibly verbose about the exact meaning of "offset":
The problem with OFFSET is that this operator has become ambiguous. The - original - purpose of the OFFSET operator is to return the offset part of a label. For Masm, a label consists of segment, offset and type information. From this point of view, it's illegal to feed OFFSET with an indirect memory operand ( and JWasm is wrong to accept [esi+0], this will be fixed). However, OFFSET in Masm additionally accepts numbers, structure names and structure fields, which aren't labels. The "offset" of a structure field is a useful information, but "offset" of numbers/structure names are useless. Also, IMO, since structure fields are accepted as operands, there's no good reason why stack variables are NOT accepted?
|
|
|
Logged
|
|
|
|
jj2007
|
The Masm workaround I use for the large BSS data is:
.data? COMM MyBigBuffer:dword:12345678
Which creates a buffer of 12345678 dwords. No messy macros, but probably doesnt work in other assemblers.
A word of caution: Communal Data Is Not Included in the LIB ListingCommunal data declarations generate no PUBLIC definitions. Therefore, although they can be placed in a library, they are not placed in the library dictionary and will not be a part of the library listing generated by the LIB utility. Communal variables are supported only by QuickC, Microsoft C versions 5.0 and later, and MASM. They are, however, similar to common blocks in FORTRAN. In C, communal variables are the uninitialized global data items. In MASM, they are data items declared with the COMM qualifier. The linker will assume the communal variables refer to an external defining declaration elsewhere. If there is no external definition, the linker allocates storage and initializes it to 0 (zero). If there is more than one declaration, storage is allocated for the largest data item declared. For example, if I is declared int I; in one module and char I; in another module, the linker will allocate 2 bytes for I because the int is 2 bytes but the char is only 1 byte. Because memory for communal variables may not be assigned until load time, their use may reduce the size of your executable file. When a communal variable is declared in a library and defined in one of the object modules, references to that variable will be resolved with the defined variable. For this reason, communal variable declarations are not recommended for any file that might be placed in a library. If a variable defined in a .OBJ file accidentally had the same name as a communal variable in a library that it is being linked with, its value would unexplainably change every time you called a library function that used that communal variable! The linker does not issue a warning because the variable was defined only once, in the OBJ file. As for other bugs... I don't even know where to begin in regards to all the quirks of the macro language that have become 'features'
Every language has its known prob... pardon: features. The ones that 'count' are those that lead to endless unnecessary bug searches. In this context, there should be a Beginner's Guide to Masm Quirks. This should include serious Masm bugs, but also simple things like the ABI ("why does the beast destroy my precious eax?"), and hints to common errors such as ".if eax<-3" - I spent a lot of time chasing this "non-bug" simply because I didn't know that Masm was stupid enough to treat eax as unsigned. Since then I happily use signed equ sdword ptr .if signed eax<-3
|
|
|
Logged
|
|
|
|
drizz
|
The two most serious bugs that are present in ml versions prior to 9.00.30729.01 are: 1) pushing of non dword variables/registers in invoke (also the zero/sign extension is silly) 2) dup with initialized structs here's a link to more links :) http://www.masm32.com/board/index.php?topic=8758.msg63746#msg63746the workaround is to use the JWASM  . Or the latest version of ml
|
|
|
Logged
|
The truth cannot be learned ... it can only be recognized.
|
|
|
jj2007
|
Just found another cute "bug": mov eax, [ esi+ecx+ebp-14] gets without warning encoded as mov eax, [ecx+ebp-14] I urgently needed that three-register address mode, but no luck 
|
|
|
Logged
|
|
|
|
jj2007
|
... 3. The offset problem: Both versions of this code work for ml 6.14 and JWasm but ml 9.0 says error A2070:invalid instruction operands .data MyAccels ACCEL <FCONTROL or FVIRTKEY, VK_S, IdMenuSave> LastAccel ACCEL <FVIRTKEY, VK_ESCAPE, IdEscape> ... .code invoke CreateAcceleratorTable, addr MyAccels, 1+(offset LastAccel-MyAccels)/SIZEOF ACCEL
invoke CreateAcceleratorTable, addr MyAccels, 1+(dword ptr LastAccel-dword ptr MyAccels)/(SIZEOF ACCEL)
No workaround found yet, except sacrificing a register... Problem solved:.data MyAccels ACCEL <FCONTROL or FVIRTKEY, VK_S, IdMenuSave> ACCEL <FVIRTKEY, VK_F5, IdButton1> ACCEL <FCONTROL or FVIRTKEY, VK_N, IdMenuNew> LastAccel ACCEL <FVIRTKEY, VK_ESCAPE, IdEscape> ... .code ... CASE WM_CREATE ; -------------------- create keyboard shortcuts -------------------- if 0 push dword ptr 1+(LastAccel-MyAccels)/SIZEOF ACCEL push offset MyAccels call CreateAcceleratorTable ; OPT_Assembler JWasm ; does not work with invoke, but pushing helps else @CatStr(<invoke CreateAcceleratorTable, offset MyAccels, >, %dword ptr 1+(LastAccel-MyAccels)/SIZEOF ACCEL) endif
Both versions work with ml 6.14, 6.15, 9.0 and JWasm.
|
|
|
Logged
|
|
|
|
|
Pages: [1]
|
|
|
 |