Title: List of known MASM bugs Post by: jj2007 on December 03, 2008, 10:19:10 PM Japheth has already made an attempt (http://www.masm32.com/board/index.php?topic=9835.msg72092#msg72092) 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. Code: 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: Code: .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 (http://www.masm32.com/board/index.php?topic=8602.msg62638#msg62638)and MichaelW): (EDIT: link to drizz' post added - thanks Michael) Code: 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 Code: .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... Title: Re: List of known MASM bugs Post by: KeepingRealBusy on December 04, 2008, 03:18:50 AM JJ,
Here is another bug in MASM 8.0 AND still in MASM 9.0. I reported this to MS: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=356393 Dave. Title: Re: List of known MASM bugs Post by: KeepingRealBusy on December 04, 2008, 03:22:40 AM JJ,
Here is another one. http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=362492 Dave. Title: Re: List of known MASM bugs Post by: MichaelW on December 04, 2008, 03:42:42 AM JJ,
The workaround for big buffers in the .data? section was from drizz, I just tested it. http://www.masm32.com/board/index.php?topic=8602.msg62638#msg62638 Title: Re: List of known MASM bugs Post by: jj2007 on December 04, 2008, 08:04:38 AM Quote from: KeepingRealBusy on December 04, 2008, 03:18:50 AM JJ, Here is another bug in MASM 8.0 AND still in MASM 9.0. I reported this to MS: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=356393 Dave. Code: Calc PROTO,dPercent:DWORD So what are you asking poor ml to do, Dave? What is the meaning of an "empty argument"?... Calc PROC, dPercent:DWORD ret Calc ENDP EDIT: Strangely enough, the empty argument is not the culprit - the commas after PROTO and PROC are being ignored. Since REC_PTRS EQU 12: Code: 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] ? Title: Re: List of known MASM bugs Post by: jj2007 on December 04, 2008, 10:41:46 AM Quote from: KeepingRealBusy on December 04, 2008, 03:18:50 AM JJ, Here is another bug in MASM 8.0 AND still in MASM 9.0. I reported this to MS: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=356393 Dave. Here is a minimalist demo of this behaviour: Code: 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 (http://msdn.microsoft.com/en-us/library/009k3eeh(VS.80).aspx) operator OFFSET Returns the offset of expression. Title: Re: List of known MASM bugs Post by: Rockoon on December 04, 2008, 12:05:57 PM 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' Title: Re: List of known MASM bugs Post by: japheth on December 04, 2008, 01:18:56 PM Quote from: jj2007 on December 04, 2008, 10:41:46 AM 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? Title: Re: List of known MASM bugs Post by: jj2007 on December 04, 2008, 02:39:44 PM Quote from: Rockoon on December 04, 2008, 12:05:57 PM 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 Listing (http://support.microsoft.com/kb/79857) Communal 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. Quote: 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 Title: Re: List of known MASM bugs Post by: drizz on December 04, 2008, 08:10:22 PM 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#msg63746 the workaround is to use the JWASM :U. Title: Re: List of known MASM bugs Post by: jj2007 on April 28, 2009, 07:05:04 PM 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 :bg Title: Re: List of known MASM bugs Post by: jj2007 on November 19, 2010, 07:02:09 PM Quote from: jj2007 on December 03, 2008, 10:19:10 PM ... 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 Code: .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: Code: .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.
The MASM Forum Archive 2004 to 2012 | Powered by SMF 1.0.12.
© 2001-2005, Lewis Media. All Rights Reserved. |