|
From: randyhyde on 2 Jun 2005 23:15 The recent exchange concerning the age-old bug in RosAsm has suggested that the problems with RosAsm crashing are due to having a large percentage of symbols in a program relative to the size of the source file. Not that RosAsm should crash under these circumstances of course, but I decided to be fair and try to "work around" this problem as Rene expects his users to do. So I wrote a short little HLA program that would generate a text file that I could "cut & paste" into an existing RosAsm program (Base3.exe) to test this theory out. Here's the HLA program that generates the source code: program main; #include( "stdlib.hhf" ) begin main; for( mov(0, ecx); ecx<10; inc( ecx )) do stdout.put( "[a", ecx, ' ', (type uns32 ecx), "]", nl ); stdout.put( "mov al, B$a", ecx, nl ); endfor; for( mov(10, ecx); ecx<1000; inc( ecx )) do lea( edx, [ecx-10] ); lea( ebx, [ecx-5] ); lea( eax, [ecx-1] ); stdout.put ( "[a", ecx, " (a", edx, "+", "a", ebx, "+", "a", eax, "+", (type uns32 ecx), ")]", nl ); stdout.put( "mov al, a", ecx, nl ); endfor; end main; Each iteration of the loop generates two statements - an equate and a mov instruction that loads AL (okay, really should have been EAX, but we'll ignore that for now) with the value of that equate. Note that, although the expressions are fairly complex, it's not like I'm generating *really* long strings that a simple textual substitution equate processor would choke on (due to buffer overflows). Here are the first several lines taken from the file that this HLA program produces: [a0000_0000 0] mov al, B$a0000_0000 [a0000_0001 1] mov al, B$a0000_0001 [a0000_0002 2] mov al, B$a0000_0002 [a0000_0003 3] mov al, B$a0000_0003 [a0000_0004 4] mov al, B$a0000_0004 [a0000_0005 5] mov al, B$a0000_0005 [a0000_0006 6] mov al, B$a0000_0006 [a0000_0007 7] mov al, B$a0000_0007 [a0000_0008 8] mov al, B$a0000_0008 [a0000_0009 9] mov al, B$a0000_0009 [a0000_000A (a0000_0000+a0000_0005+a0000_0009+10)] mov al, a0000_000A [a0000_000B (a0000_0001+a0000_0006+a0000_000A+11)] mov al, a0000_000B [a0000_000C (a0000_0002+a0000_0007+a0000_000B+12)] mov al, a0000_000C [a0000_000D (a0000_0003+a0000_0008+a0000_000C+13)] mov al, a0000_000D Now if you cut & paste this (short) code sequence into the RosAsm Base3.exe program, RosAsm will compile it just fine. So what happens when we cut and paste the entire 2,000 lines? As I've come to expect, RosAsm crashes and all data is lost (sorry, Ludwig, the "crash manager" did not save the file before crashing; the data I pasted into Base3.exe was lost). Okay, RosAsm chokes on 1,000 statement pairs. It did work on about 13 statement pairs. Perhaps RosAsm can handle a fair number of these? Nope. I put in 20 pairs of these statements, that is: [a0000_0000 0] mov al, B$a0000_0000 [a0000_0001 1] mov al, B$a0000_0001 [a0000_0002 2] mov al, B$a0000_0002 [a0000_0003 3] mov al, B$a0000_0003 [a0000_0004 4] mov al, B$a0000_0004 [a0000_0005 5] mov al, B$a0000_0005 [a0000_0006 6] mov al, B$a0000_0006 [a0000_0007 7] mov al, B$a0000_0007 [a0000_0008 8] mov al, B$a0000_0008 [a0000_0009 9] mov al, B$a0000_0009 [a0000_000A (a0000_0000+a0000_0005+a0000_0009+10)] mov al, a0000_000A [a0000_000B (a0000_0001+a0000_0006+a0000_000A+11)] mov al, a0000_000B [a0000_000C (a0000_0002+a0000_0007+a0000_000B+12)] mov al, a0000_000C [a0000_000D (a0000_0003+a0000_0008+a0000_000C+13)] mov al, a0000_000D [a0000_000E (a0000_0004+a0000_0009+a0000_000D+14)] mov al, a0000_000E [a0000_000F (a0000_0005+a0000_000A+a0000_000E+15)] mov al, a0000_000F [a0000_0010 (a0000_0006+a0000_000B+a0000_000F+16)] mov al, a0000_0010 [a0000_0011 (a0000_0007+a0000_000C+a0000_0010+17)] mov al, a0000_0011 [a0000_0012 (a0000_0008+a0000_000D+a0000_0011+18)] mov al, a0000_0012 [a0000_0013 (a0000_0009+a0000_000E+a0000_0012+19)] mov al, a0000_0013 [a0000_0014 (a0000_000A+a0000_000F+a0000_0013+20)] mov al, a0000_0014 And RosAsm crashes, losing all data in memory. Bzzzzzzt. Game over. Sorry Ludwig, sorry Rene. There is a *serious* problem here. You can't blame it on not allocating a sufficient amount of memory. You can't claim that it's okay because the crash manager preserves the file should a crash actually occur. You can't claim that no one would ever create a program with *so many* equates (we're talking *20* equates here). If such a trivially simple program crashes RosAsm, how can anyone trust this program? And mind you, it's not like I set out to find the smallest program that would crash RosAsm. This is the first thing I tried. Attempting to avoid the programs I wrote in the past that crashed RosAsm, I tried a completely different approach this time. I was more interested in measuring RosAsm's speed than trying to crash it; once again I've found that messing with RosAsm is simply a waste of time. BTW, it goes without saying that I downloaded the latest version of RosAsm prior to running this test. Cheers, Randy Hyde P.S. For the record, here's the Base3.exe source file, showing where I cut & paste the code. As you can clearly see, the issue of source file size compared to number of equates is a non-issue here: ___________________________________________________________________________________________ ___________________________________________________________________________________________ ; Base3.exe Example with Standard Menu and set of Macros. ; ; Hll Style version. ; ; This HLL version is the one I will continue to use in my Tuts and Demos. It is somewhat less ; HLL like than Base4.exe and closer to the RosAsm basic rules. I.E. Beginner friendly. ; ; // 'api' Macros of Base2.exe are stripped off: a Tasm like 'Call' instead (works the same). ; // The default 'D' for local Labels is required to conform with the basic syntax. ; // The 'Proc' Macros do not include the control for transmitted parameters number. ___________________________________________________________________________________________ ___________________________________________________________________________________________ ; Some basic Macros: [push | push #1 | #+1] [pop | pop #1 | #+1] [mov | mov #1 #2 | #+2] [inc | inc #1 | #+1] [dec | dec #1 | #+1] [On | cmp #1 #3 | jn#2 o1> | #4>L | o1:] [call | push #L>2 | call #1] [move | push #2 | pop #1 | #+2] [If | cmp #1 #3 | jn#2 I0>] [.If | cmp #1 #3 | jn#2 I1>>] [..If | cmp #1 #3 | jn#2 I2>>] [...If | cmp #1 #3 | jn#2 I3>>] [Else_if | jmp I5> | I0: | cmp #1 #3 | jn#2 I0>] [.Else_if | jmp I6>> | I1: | cmp #1 #3 | jn#2 I1>>] [..Else_if | jmp I7>> | I2: | cmp #1 #3 | jn#2 I2>>] [...Else_if | jmp I8>> | I3: | cmp #1 #3 | jn#2 I3>>] [Else | Jmp I5> | I0:] [.Else | Jmp I6>> | I1:] [..Else | Jmp I7>> | I2:] [...Else | Jmp I8>> | I3:] [End_if | I0: | I5:] [.End_if | I1: | I6:] [..End_if | I2: | I7:] [...End_if | I3: | I8:] ; If_Or eax = 1, eax = 5, eax =122 [If_Or | cmp #1 #3 | j#2 O0> | #+3 | jmp I0> | O0:] [.If_Or | cmp #1 #3 | j#2 O1> | #+3 | jmp I1> | O1:] [..If_Or | cmp #1 #3 | j#2 O2> | #+3 | jmp I2> | O2:] [...If_Or | cmp #1 #3 | j#2 O3> | #+3 | jmp I3> | O3:] ; If_And eax = 1, ebx = 5, ecx =122 [If_And | cmp #1 #3 | jn#2 I0> | #3] [.If_And | cmp #1 #3 | jn#2 I1> | #3] [..If_And | cmp #1 #3 | jn#2 I2> | #3] [...If_And | cmp #1 #3 | jn#2 I3> | #3] [While | W0: | cmp #1 #3 | jn#2 W9>] [End_While | jmp W0< | W9:] [.While | X0: | cmp #1 #3 | jn#2 X9>>] [.End_While | jmp X0<< | X9:] [Do | D0:] [Loop_Until | cmp #1 #3 | jn#2 D0<] [Do_Loop | Loop D0<] [.Do | E0:] [.Loop_Until | cmp #1 #3 | jn#2 E0<<] ; long [.Do_Loop | Loop E0<] _________________________________________________________________________________________ ; Added Equates for a more HLL like style in comparison to Macros: [= e < b > a =< be <= be => ae >= ae <> ne] _________________________________________________________________________________________ _________________________________________________________________________________________ ; Proc Macros and Equates. Internal storages are: ; ; &1 <<< Size of Argument(s) (for ending Ret n, in EndP). Set by Argument(s) ; &2 <<< Size of Local (for Stack Management). Set by Local ; &3 <<< What to pop before ret. Set by User. [Proc | &1=0 | &2=0 | &3= | #1 | push ebp | mov ebp esp] [Exit | jmp P9>>] [Arguments | {#1 Arg#x} | #+1 | &1=SizeOf#x] [Argument | {#1 Arg#x} | #+1 | &1=SizeOf#x] [Local | {#1 Local#x} | #+1 | sub esp SizeOf#x | &2=SizeOf#x] [StrucPtrs | {#3 ebp+#2+#F} | #+2] [Structure | {#1 ebp-&2-4} | sub esp #2+4 | mov D$#1 esp | StrucPtrs 0-&2-#2-4 #L>3] [Uses | push #1>L | &3=pop #L>1] [EndP | P9: | &3 | mov esp ebp | pop ebp | ret &1] ; For pointing to transmitted parameters (upper "Arg#x" fall here): [Arg1 ebp+8 Arg2 ebp+12 Arg3 ebp+16 Arg4 ebp+20 Arg5 ebp+24 Arg6 ebp+28 Arg7 ebp+32 Arg8 ebp+36 Arg9 ebp+40 Arg10 ebp+44] ; For pointing Local Stack declared data (upper "Local#x" fall here): [Local1 ebp-4 Local2 ebp-8 Local3 ebp-12 Local4 ebp-16 Local5 ebp-20 Local6 ebp-24 Local7 ebp-28 Local8 ebp-32 Local9 ebp-36 Local10 ebp-40] ; To help preventing from stack sizes' mistakes (upper "SizeOf#x" fall here): [SizeOf1 4 SizeOf2 8 SizeOf3 12 SizeOf4 16 SizeOf5 20 SizeOf6 24 SizeOf7 28 SizeOf8 32 SizeOf9 36 SizeOf10 40] _________________________________________________________________ [Argh: 'Aaarrrghhh!!!!....', 0 Whaoo: 'Whaaaaoooo!!!!....', 0] [MessageBox | {&0: #2 0} | call 'USER32.MessageBoxA' &NULL &0 #1 &MB_SYSTEMMODAL__&MB_OK] ; ... to be called, for example, by: ; ; > MessageBox Whaoo 'Oh! No, please!!! not that again!...' ___________________________________________________________________________________________ ; Data: [FirstMessage: 0 #7] ; For "GetMessage" [WindowClass: ; Window Class Structure style: 3 lpfnWndProc: MainWindowProc cbClsExtra: 0 cbWndExtra: 0 hInstance: 0 hIcon: 0 hCursor: 0 hbrBackground: 6 lpszMenuName: 0 lpszClassName: WindowClassName] [WindowHandle: 0 MenuHandle: 0] [WindowClassName: B$ 'Anything' 0 WindowCaption: 'Base App' 0] [WindowX: 50 WindowY: 50 WindowW: 650 WindowH: 450] ___________________________________________________________________________________________ Main: call 'Kernel32.GetModuleHandleA' 0 | mov D$hInstance eax call 'User32.LoadIconA' D$hInstance 1 | mov D$hIcon eax call 'User32.LoadCursorA' 0 &IDC_ARROW | mov D$hCursor eax call 'User32.RegisterClassA' WindowClass call 'User32.LoadMenuA' D$hInstance M00_Menu | mov D$MenuHandle eax call 'User32.CreateWindowExA' &WS_EX_CLIENTEDGE WindowClassName WindowCaption, &WS_OVERLAPPEDWINDOW__&WS_VISIBLE, D$WindowX D$WindowY D$WindowW D$WindowH 0, D$MenuHandle D$hInstance 0 mov D$WindowHandle eax call 'User32.ShowWindow' D$WindowHandle &SW_SHOW call 'User32.UpdateWindow' D$WindowHandle jmp L1> While eax <> 0 call 'User32.TranslateMessage' FirstMessage call 'User32.DispatchMessageA' FirstMessage L1: call 'USER32.GetMessageA' FirstMessage 0 0 0 End_While call 'Kernel32.ExitProcess' &NULL ___________________________________________________________________________________________ ; These menu equates are given by the menu editor ([ClipBoard]): [M00_Menu 2000 M00_New 2001 M00_Open 2002 M00_Save 2003 M00_Save_As 2004 M00_Exit 2005 M00_Undo 2006 M00_Cut 2007 M00_Copy 2008 M00_Paste 2009 M00_Delete 2010 M00_Select_All 2011 M00_About 2012] ___________________________________________________________________________________________ Proc MainWindowProc: Arguments @Adressee @Message @wParam @lParam pushad .If D(a)Message = &WM_CLOSE call 'USER32.DestroyWindow' D(a)Adressee .Else_If D(a)Message = &WM_DESTROY call 'User32.PostQuitMessage' 0 .Else_If D(a)Message = &WM_COMMAND If D(a)wParam = M00_Exit call 'User32.SendMessageA' D(a)Adressee &WM_CLOSE 0 0 ; Else_If D(a)wParam = M00_... ; ... ; Else_If D(a)wParam = M00_About ; ... Else MessageBox InfoTitle " This file is not a Demo. It is a 'StartUp' Base You can use to develop your own work. " End_If .Else popad call 'User32.DefWindowProcA' D(a)Adressee D(a)Message D(a)wParam D(a)lParam Exit .End_If popad | mov eax &FALSE [a0000_0000 0] mov al, B$a0000_0000 [a0000_0001 1] mov al, B$a0000_0001 [a0000_0002 2] mov al, B$a0000_0002 [a0000_0003 3] mov al, B$a0000_0003 [a0000_0004 4] mov al, B$a0000_0004 [a0000_0005 5] mov al, B$a0000_0005 [a0000_0006 6] mov al, B$a0000_0006 [a0000_0007 7] mov al, B$a0000_0007 [a0000_0008 8] mov al, B$a0000_0008 [a0000_0009 9] mov al, B$a0000_0009 [a0000_000A (a0000_0000+a0000_0005+a0000_0009+10)] mov al, a0000_000A [a0000_000B (a0000_0001+a0000_0006+a0000_000A+11)] mov al, a0000_000B [a0000_000C (a0000_0002+a0000_0007+a0000_000B+12)] mov al, a0000_000C [a0000_000D (a0000_0003+a0000_0008+a0000_000C+13)] mov al, a0000_000D EndP ______________________________________________________________________________________ ; little message routines for values tests (dWords only / text pointer) to be called with: ; > Hexprint D$esi / showme esi+5, for example: [InfoTitle: 'Application Base', 0] [HexprintString: B$ ' h' 0 MessageTitle: 'HihoHiho' 0] Proc HexPrnt: Arguments @N pushad mov ebx D@N, ecx 8, edi HexPrintString | add edi 7 std Do mov al bl | and al 0F | add al '0' On al > '9', add al 7 stosb | shr ebx 4 Do_Loop cld call 'USER32.MessageBoxA' 0 HexPrintString MessageTitle &MB_OK__&MB_SYSTEMMODAL popad EndP [Hexprint | call Hexprnt #1 | #+1] Proc ShowYou: Arguments @Pointer pushad call 'USER32.MessageBoxA' &NULL D(a)Pointer MessageTitle &MB_SYSTEMMODAL__&MB_OK popad EndP [Showme | push eax | lea eax D$#1 | call ShowYou eax | pop eax] _______________________________________________________________________________________
From: Betov on 3 Jun 2005 04:18 randyhyde(a)earthlink.net ýcrivait news:1117768517.847816.306860(a)o13g2000cwo.googlegroups.com: :))))) I already told you that this "problem" :)) will be kept preciously alive, forever, in order to make it impossible for you to do what you want to do. For the RosAsm users who would want to do such a stupid thing (they are allowed to do stupid things, if they like to...), i tell them how to do it, under the expressed condition that they promiss to not make it public. :) Betov. < http://rosasm.org >
From: hutch-- on 3 Jun 2005 04:37 Come on Betov, the only leg you are pulling here is your own (I won't say which one as it may make Annie blush). RosAsm falls over with anything above trivial data and you just don't know how to fix it. Maybe you should tie a knot in IT instead and start learning something about data structures. Muhahahaha hutch at movsd dot com
From: Frank Kotler on 3 Jun 2005 09:11 Betov wrote: > For the RosAsm users who would want to do such a stupid > thing (they are allowed to do stupid things, if they like > to...), i tell them how to do it, under the expressed > condition that they promiss to not make it public. > > :) Jeez! I hope the anti-GPL forces don't learn of this technique! Best, Frank
From: justonce on 3 Jun 2005 15:22
Hi, I'm very new to assembly so I tried to understand the first message in that thread. I didn't understand it. I downloaded Rosasm, pasted the code : it compiled, run in the debuger and as expected, when I closed the window, the debuger showed the message : ACCESS VIOLATION [C0000005] The thread tried to read from or write to a virtual address for which it does not have the appropriate access. Instruction that raised the exception : mov al B$0 Normal, Windows doesn't allow access at ram address 0. In fact, you don't need 1000 or even 13 instructions. Only one is enough : [a0000_0000 0] mov al, B$a0000_0000 or simpler : mov al B$0 I tried then with Hide. I don't know all the strange syntax for this assembler, so I changed the code mov ebx 0 mov al B$ebx So in Hide : // hello world console demo // for more projects and sources, // download the HIDE Projects package program hw_console; #includeonce("stdlib.hhf") begin hw_console; stdout.put("Hello world of assembly",nl); mov( 0, ebx ); mov([ebx], eax); end hw_console; And of course, the compiled program raises an exception. So, I don't understand : what is Mr Hyde talking about ?? Please help me to understand. Regards. |