Hi all,
Just a short introduction how to use a new feature in hjwasm.
It can be used with integers which need to be put in eax register.
Cases can contain decimal or hexadecimal integers.
Now you can also use hexadecimal numbers in C stile (0x or 0X) prefix.
.SWITCH can be used without 'eax', however, it is easier to understand code if 'eax' is present.
Inside the .case and .break you can write your code or function calling
The body of .SWITCH - .CASE - .DEFAULT - .ENDSWITCH must have all 4 elements present.
Here are some examples:
;//this one will use .if .elseif
mov eax,280
.switch eax
.case 273
mov edx,273
.break
.case 280
mov edx,280
.break
.case 275
mov edx,275
.break
.default
mov edx,0
.break
.endswitch
;//this one will use binary tree search because max - min is greater than 256
;//binary tree search is very fast and you can have cases more than 256
mov eax,252h
.switch eax
.case 2
.case 5
.case 6
mov edx,2
.break
.case 280h
mov edx,280h
.break
.case 252h
mov edx,252h
.break
.case 274h
mov edx,274h
.break
.case 277
mov edx,277h
.break
.case 281
mov edx,281h
.break
.case 269h
mov edx,269h
.break
.case 282h
mov edx,282h
.break
.case 283h
mov edx,283h
.break
.case 286h
mov edx,286h
.break
.default
mov edx,0
.break
.endswitch
;//this one will use jump table because max - min is inside 256
;//jump table is based on 1 byte pointer, that is why you can have maximum of 256 cases
mov eax,0x1252
.switch eax
.case 0x1273
mov edx,0x1273
.break
.case 0x1280
mov edx,0x1280
.break
.case 0x1252
mov edx,0x1252
.break
.case 0x274
mov edx,0x1274
.break
.case 277
mov edx,0x1277
.break
.case 0x1281
mov edx,0x1281
.break
.case 0x1269
mov edx,0x1269
.break
.case 0x1282
mov edx,0x1282
.break
.case 0x1283
mov edx,0x1283
.break
.case 0x1286
mov edx,0x1286
.break
.default
mov edx,0
.break
.endswitch
I just want to tank Johnsa for request of that feature and for his involvement in designing, creating and testing it :t
I also thank you JJ2007 for your 'Magic Macro' although I could not use it as it was, but it gave me a great insight how to do it.
I also have to thank bitRake for his macro, which gave me some idea how to use binary tree search, although his binary tree search is recursive which can cause a stack overflow.
here is a simple but effective function which I used for the binary tree search:
while (low <= high) {
int mid = (low + high) / 2;
if (pcases[mid] == casen)
return mid;
else if (pcases[mid] < x)
low = mid + 1;
else high = mid - 1;
}
Now alignment 16 (xmm) or 32(ymm) byte for locals has been fixed in PROC FRAME
If you want locals to be aligned you have to put them on the top
There is a problem with 32 byte alignment because system doesn't give you 32 but 16 byte aligned
so we have to do it manually, at the start of our program, to make we have it aligned properly.
We should do it in the startup only ones and hjwasm will than take care that all next function have the proper alignment
I have to remind you as well that since AVX supports ymm registers we can not any more push xmm registers as parameters but ymm registers
so for example:
WinMain proc FRAME uses rbx xmm6 xmm7 hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:UINT
will cause an error. You have to use :
WinMain proc FRAME uses rbx ymm6 ymm7 hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:UINT
WinMainCRTStartup proc FRAME
;// Because the system doesn't provide 32 byte alignment
;// This four lines will ensure that alignment in next procedures
mov rax, [rsp] ;// keep return address in rax
add rsp, 32 ;// make sure wee don't delete some important data on the stack
and rsp, 0FFFFFFFFFFFFFFE0h ;// align it to 32 byte
mov [rsp], rax ;// put return addres again on the stack
invoke GetModuleHandleA, NULL
mov hInstance, rax
invoke GetCommandLine
mov CommandLine, rax
invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
invoke ExitProcess, eax
WinMainCRTStartup endp
I attached one simple example to see how it looks like in 64 bite
deleted
When aligning data to 32 or 64 byte (not bite) be aware that the first var in .data? segment will not be aligned
but the second will:
.data?
align 32
testloc3 XMMWORD ? ;// not aligned
align 32
testloc2 YMMWORD ? ;// aligned
in .data segment the first var is aligned
.data
align 32
testloc YMMWORD 0 ;// aligned to 32 byte
test1 dq 0 ;// aligned to 32 byte
align 32 ;// after QWWORD we have to align it again manualy
testloc1 YMMWORD 0;//aligned to 32 byte
nidud, Johnsa and I have concluded that .ENDSWITCH is more appropriate than .ENDSW and that we both like it more
Habran,
Why are you using the C format of .break ? There is no gain from doing it that way and even K&R thought that it should have been done in the original design of C as a language.
deleted
deleted
nidud, @CCCD0 means that labels are not saved in uint_16 *plabels;
I had that while working on it. Maybe Johnsa put an older version of hll.c
I will attach here the proper version and than see if it will work with it
Hi hutch :biggrin:
I don't understand what are you trying to say :dazzled:
.break is important part of HLL in masm, jwasm and now in hjwasm
C uses break without a leading dot :icon_exclaim:
Please explain
deleted
What about if you add one more case
try with this if it works:
mov eax,280
.switch eax
.case 273
mov edx,273
.break
.case 280
mov edx,280
.break
.case 275
mov edx,275
.break
.case 283
mov edx,283
.break
.default
mov edx,0
.break
.endswitch
I have to go now but I will be bck in about two hours than I will see if what is appening
if you will be here we can find what is the problem
It was working on my computer
Habran,
"break" or ".break" is a redundancy left over from the early days of C language design that is not needed in a "switch" block. A "switch" block should automatically exit each option to the end of the switch block.
switch condition
case 1
do this
case 2
do that
case else
do default
endsw(itch)
All "break" or ".break" gives you is extra typing. We already have a macro that does this in MASM32.
Hi hutch,
thanks for that, sounds reasonable, I will see if I can make it work that way, I like the idea :t
Hi nidud, I can see that there is a problem with 32 bit in first case, second and third work fine
I will work on that today and hopefuly fix it
thanks for the bugfind :t
deleted
deleted
I am following hutch's suggestion and I have already make it work without .break but without having to use JMP,
jump is built inside the case.
I have only to find a solution for multiple cases like
.case 1
.case 2
.case 3
mov edx, 3
.case 4
mov edx,4
deleted
nidud, that is pretty good solution, however, I want to make it similar to C stile, I know there is the way to do that but I have to take some time to find that way
I will still go through everything and try to fix 32 bit. It works on my computer but if I change the position of those three examples I've got error A2168: General Failure
Please, be patient
deleted
the problem appears if we have EG:
case 2
case 5
case 9
in that case 1, case 3, case 4, case 6 , case 7 and case 8 are default
so it would be incorect to use 2..9
I like idea to depreciate .break, so I will find the solution how to build in the:
.case 2
.case 5
.case 9
mov edx, 9
.case 11
mov edx,11
I am going to do that now 8)
After a little bit of pondering and cooling off period, I decided to disappoint hutch (sorry mate) and give up on removing
the .BREAK
It gives to programmer more control over the code.
Because of a FIXED STACK FRAME we can not just jump to subroutines because it will cause a chaos in the program,
we have to use invoke or call inside the case but not jmp
So, I will only work on fixing 32 bit and enhancing the intelligence of the .SWITCH - .CASE - .DEFAULT - .ENDSWITCH
Perhaps I have misunderstood what you are doing but a switch block should have a label at the end of it once the macro is expanded so that instead of having to add "break" like old format C, if an case matches the comparison, it will perform that act then branch to the end label.
In 64 bit it will be something like this for each case statement.
lbl:
cmp rax, value
jne nxtlbl
perform action
jmp end_lbl
I take you point that a direct jump out of any procedure is dangerous as it will mess up the allocated spill space but that is not part of the design of a switch block that should only operate within an given procedure. If you want to construct a branch address table you probably can do it a bit faster but a standard sequential compare is probably fast enough in almost all cases.
.break is exactly doing this but we don't need to give name to label exit because .break is doing just that
JMP LOOP_EXIT
cmp rax, value
jne nxtlbl
perform action
.break ;jmp end_lbl
:biggrin:
Yeah, I know exactly what "break" does but my comment was in the first place, you gain nothing from adding it into a switch block where the win is supposed to be simplicity. Long ago I read an interview with both K and R and one of their laments was that the C language required the extra instruction "break" after each "case" in a switch block but that it was too late to change it. Unless you are directly aping this characteristic in C, it serves no purpose as part of the required structure of a switch block.
Still, if that's what you want, I hope it works well for you, as long as the macro system works well, there are enough folks around who can bypass this with a MASM style macro.
Quote from: hutch-- on April 12, 2016, 05:08:34 PMthere are enough folks around who can bypass this with a MASM style macro
;)
include \masm32\include\masm32rt.inc
option dotname
.Switch equ Switch
.Case equ Case
.Default equ Default
.Endsw equ Endsw
.code
start:
or ebx, -1
m2m esi, 7
.Repeat
print str$(ebx), 9
.Switch ebx
.Case 1
print "Case 1", 13, 10
.Case 0
print "NULL", 13, 10
.Case 2
print "Case 2", 13, 10
.Case 3 .. 5
print "Case three to five", 13, 10
.Case esi
print "matches esi", 13, 10
.Default
print "Default", 13, 10
.Endsw
inc ebx
.Until ebx>9
inkey "that was difficult, right?"
exit
end start
deleted
deleted
Thanks nidud :t
Quote from: nidud on April 12, 2016, 08:28:47 PM
1312 cycles, rep(100), code(1920) - .switch - no match
21844 cycles, rep(100), code(1481) - SWITCH - no match (MasmBasic)
Can you post source & exe, please?
deleted
Hi nidud,
Can you please upload your project with HJWasm so that I can debug it and see where is that bug
It doesnt have to be here, just send me the site address.
If you don't want to do it here you cam PM me
deleted
deleted
deleted
Quote from: nidud on April 12, 2016, 11:42:02 PM
mbswitch proc value
mov eax,value
SWITCH eax
enum_mb = 0
repeat count
case enum_mb
mov eax,enum_mb
enum_mb = enum_mb + 1
endm
default
xor eax,eax
ENDSW
ret
mbswitch endp
That is the classical Masm32 Switch macro. MasmBasic Switch_ (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1285) looks different, and behaves differently:
1255 cycles, rep(96), code(1844) for swproc
980 cycles, rep(96), code(2825) for MB Switch_
20555 cycles, rep(96), code(1421) for Masm32 switch
20456 cycles, rep(96), code(1430) for ifproc
The count is too high for the MasmBasic Switch_ macro, but
count equ 96 works, see attachment.
deleted
I must admit I have no idea what this code does:
swproc proc value ; OPT_Assembler asmc
mov eax,value
int 3
.SWITCH eax
enum = 0
repeat count
.case enum
mov eax,enum
.break
enum = enum + 1
endm
ifdef __HJWASM__
.default
xor eax,eax
.break
endif
MENDSW
@CCCD0:
ret
swproc endp
Under the hood:
0040209F Ú$ 55 push ebp ; timeit.0040209F(guessed Arg1)
004020A0 ³. 8BEC mov ebp, esp
004020A2 ³. 8B45 08 mov eax, [arg1]
004020A5 ³. CC int3
004020A6 ³. E9 C5030000 jmp 00402470
004020AB ³> B8 00000000 mov eax, 0
004020B0 ³. E9 1B070000 jmp 004027D0
004020B5 ³> B8 01000000 mov eax, 1
....
004027BE ³. 83F8 60 cmp eax, 60
004027C1 ³. 0F84 90FCFFFF je 00402457
004027C7 ³. 83F8 60 cmp eax, 60
004027CA ³. 0F84 91FCFFFF je 00402461
004027D0 ³> 5D pop ebp
004027D1 À. C2 0400 retn 4
::)
Don't forget ObjAsm also have a switch, that say is a modification a Greg Falen one (MASM32).
I used only one time. Apparently support multiple case in one line: case 1, 4, 6, etc
1293 cycles, rep(96), code(1499) for swproc
1000 cycles, rep(96), code(2825) for MB Switch_
27252 cycles, rep(96), code(1421) for Masm32 switch
874 cycles, rep(96), code(1421) for ObjAsm switch
24227 cycles, rep(96), code(1430) for ifproc
hit any key to continue...
deleted
:biggrin: It's the same after each macro expansion at compilation time: repeat count ... endm. Nothing to do with test (perhaps JJ could change "count" to "limit" or something more clear).
deleted
:t
deleted
Also I introduce a case with a value of 3500. MB is fast, but become inmense for big values:
8151 cycles, rep(96), code(1828) for HJWASM
1481 cycles, rep(96), code(16461) for MB Switch_
28402 cycles, rep(96), code(1433) for Masm32 switch
27360 cycles, rep(96), code(1433) for ObjAsm switch
27170 cycles, rep(96), code(1439) for ifproc
hit any key to continue...
It's compiled with a HJWAsm modified for no collition with ObjAsm (.for is .forh, etc).
A diferent compilation with ASMC (some problem with MB):
6940 cycles, rep(96), code(1855) for ASMC
26649 cycles, rep(96), code(1433) for Masm32 switch
24479 cycles, rep(96), code(1433) for ObjAsm switch
29691 cycles, rep(96), code(1439) for ifproc
hit any key to continue...
Hi HSE,
are you using 32 bit or 64 bit HJWasm?
32 bit.
Perfect:
swproc proc value ; OPT_Assembler asmc
mov eax,value
.SWITCHh eax ; this is the line 183
enum = 0
repeat count
% .caseh @CatStr(%enum) ; nidud
;; .caseh enum ; JJ
mov eax,enum
.break
enum = enum + 1
endm ; this is the line 191
.caseh lejos
.defaulth
xor eax,eax
.break
.endswitch
@CCCD0:
ret
swproc endp
Without modification (only MASM32, no ObjAsm) :timeit2.asm(183) : Error A2209: Syntax error: .
timeit2.asm(191) : Error A2209: Syntax error: .
MacroLoop(1): iteration 1: Macro called from
timeit2.asm(191): Main line code
If I have what is going on in this discussion, its the difference between the design of an assembler and algorithm design. A traditional "switch" block in C is a sequential set of comparisons and in most cases is easily fast enough in comparison to the high level code it is used in where if you are writing bare algorithms where there is a wide range of branching, you would normally write something like a table of label addresses and substantially reduce the search overhead for the right branch.
Now the example I used years ago was for a WndProc that instead of sequential comparisons, a zero filled array was allocated in dynamic memory then for each message that you wanted to process, you wrote the label address at the correct array offset. Now as most messages occur at under 1024, it meant you could run a 4k size array which is trivial by even old standards and for the odd message that is over 1024 you did a test first and shoved it somewhere else. In high level code which a Wndproc is you could not see the difference so while it was fast, it was a "who cares" improvement.
Now to address what is being done with this discussion on structuring a "switch" block in an assembler, when you start going into specific algorithm design you are going beyond an assembler design and entering into algorithm design which is probably best left to the individual genius of programmers. You could go down the path of adding runtime support for such a mechanism but then you are turning the assembler into a compiler which may not be the target you want.
Agree with the concepts.
Very effective idea(MB table and plain code):8580 cycles, rep(96), code(1828) for HJWASM
1706 cycles, rep(96), code(16463) for MB Switch_
895 cycles, rep(96), code(1438) for mixed <----- hutch comcept
28583 cycles, rep(96), code(1433) for Masm32 switch
26762 cycles, rep(96), code(1433) for ObjAsm switch
22800 cycles, rep(96), code(1439) for ifproc
hit any key to continue...
HSE, that is not perfect yet because as far as I can see EXIT label is not getting constructed, that is why you need to use @CCCD0 after the .endswitch
I have to find out why 32 bit doesn't run properly and fix it
try to use this code and see what will happen:
Quote
mov eax,252
.switch eax
.case 273
mov edx,273
.break
.case 280
mov edx,280
.break
.case 252
mov edx,252
.break
.case 274
mov edx,274
.break
.case 277
mov edx,277
.break
.case 281
mov edx,281
.break
.case 269
mov edx,269
.break
.case 282
mov edx,282
.break
.case 283
mov edx,283
.break
.case 286
mov edx,286
.break
.default
mov edx,0
.break
.endswitch
hab1.asm(67) : Error A2102: Symbol not defined : @CCCD0
With @CCCD0 there is no problem
Error A2102: Symbol not defined : @CCCD0 should not happen
I've been tying today to find a problem but on my computer I get error A2168: General Failure
Can you send me a source you are testing with please?
Now I have the phone.
That results are with modified hjwasm. I obtain general failure or something like that with original one. Perhaps a collition with switch.
I am a bit confused with all these versions. Where exactly are latest executables of
- HJWasm with .switch
- asmc with .switch
??
JJ2007, here (http://www.terraspace.co.uk/hjwasm.html#p6)
HSE, can you please send me that modified source, so that I can find where is the bug
Quote from: habran on April 14, 2016, 05:40:13 AM
JJ2007, here (http://www.terraspace.co.uk/hjwasm.html#p6)
Thanks. HJWasm32.exe gives me general failure with the timeit.asm test, while HJWasm64 complains about rax and rdx not defined for MENDSW ::)
AsmC builds testit.asm without errors. Same for this little testbed (the .breaks should really disappear :():
include \masm32\include\masm32rt.inc
.code
swproc proc value
mov eax, value
mov ecx, 7
.Switch eax
.Case 0
print "case 0", 13, 10
.break
.Case 1
print "case 1", 13, 10
.break
.Case 2
print "case 2", 13, 10
.break
.Case ecx
print "case ecx", 13, 10
.break
.Case 10 .. 20
print str$(eax), " (case 10 .. 20)", 13, 10
.break
.Default
print str$(eax), " (default)", 13, 10
.Endsw
ret
swproc endp
start:
invoke swproc, -99
invoke swproc, 0
invoke swproc, 1
invoke swproc, 2
invoke swproc, 7
invoke swproc, 10
invoke swproc, 20
invoke swproc, 99
exit
end start
Output:
-99 (default)
case 0
case 1
case 2
case ecx
10 (case 10 .. 20)
20 (case 10 .. 20)
99 (default)
Under the hood it's a series of comparisons:
004010B4 ³> À83F8 00 cmp eax, 0
004010B7 ³. 0F84 54FFFFFF je 00401011
004010BD ³. 83F8 01 cmp eax, 1
004010C0 ³. 0F84 64FFFFFF je 0040102A
004010C6 ³. 83F8 02 cmp eax, 2
004010C9 ³. 0F84 74FFFFFF je 00401043
004010CF ³. 3BC1 cmp eax, ecx
004010D1 ³. 74 89 je short 0040105C
004010D3 ³. 83F8 0A cmp eax, 0A
004010D6 ³. 72 05 jb short 004010DD
004010D8 ³. 83F8 14 cmp eax, 14
004010DB ³. 76 95 jbe short 00401072
004010DD ³> EB B4 jmp short 00401093
You are correct, HJWasm64 can run x64 only and HJWasm32 x86 only for the SWITCH
The 32 binaries from Teraspace cause general failure.
This attached version is a debug 32 version and it does a job properly if you assemble code bellow in this order I gave
If you change the order of the code it causes general failure, when I tested 32 bit in the first hand I had that code and that is why I thought that it runs OK. I don't understand why it causes general failure if I change the order of these code bellow :dazzled:
mov eax,252
.switch eax
.case 2
mov edx,2
.break
.case 280
mov edx,280
.break
.case 252
mov edx,252
.break
.case 274
mov edx,274
.break
.case 277
mov edx,277
.break
.case 281
mov edx,281
.break
.case 269
mov edx,269
.break
.case 282
mov edx,282
.break
.case 283
mov edx,283
.break
.case 286
mov edx,286
.break
.default
mov edx,0
.break
.endswitch
mov eax,252
.switch eax
.case 273
mov edx,273
.break
.case 280
mov edx,280
.break
.case 252
mov edx,252
.break
.case 274
mov edx,274
.break
.case 277
mov edx,277
.break
.case 281
mov edx,281
.break
.case 269
mov edx,269
.break
.case 282
mov edx,282
.break
.case 283
mov edx,283
.break
.case 286
mov edx,286
.break
.default
mov edx,0
.break
.endswitch
mov eax,280
.switch eax
.case 273
mov edx,273
.break
.case 280
mov edx,280
.break
.case 275
mov edx,275
.break
.default
mov edx,0
.break
.endswitch
Hi habran!
I just add a final "h" to .for, .switch, .case and .default.
Perhaps there is a confict with the "c" language switch (but not with switchh :biggrin:)
Thanks HSE :t
your source with a little bit of tweaking works without @CCCD0 on my machine
but if I add something else same error happens
I have to go now but afternoon I'll be back 8)
Not error... and not work :redface:
Nasty .BITCH in the .SWITCH :greenclp:
I'll get that bloody bug and crush it. :badgrin:
I found the bug :badgrin:
However, the bug is not in the .SWITCH but in the GetLineNumber() function
That problem is somehow related only to 32 bit
So, if you build without /Zi, everything will work fine.
For now don't build a DEBUG version and you will be able to test .SWITCH without problems.
I will try to find the problem in GetLineNumber() function and fix it.
It must be something trivial otherwise it wouldn't work in 64 bit
I am going now to crash that .BITCH
Quote from: habran on April 14, 2016, 08:24:09 PM
That problem is somehow related only to 32 bit
So, if you build without /Zi, everything will work fine.
Sure?
*** Assemble using HJWasm32 /c /coff /Fl /Sn /Fo "timeit" ***
HJWasm v2.14, Apr 11 2016, Masm-compatible assembler.
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.
Tmp_File.asm(87) : Error A2168: General Failure
swproc proc value ; OxPT_Assembler asmc
mov eax,value ; OPT_Assembler HJWasm32
; int 3
.SWITCH eax
enum = 0
repeat count
.case enum
mov eax,enum
.break
enum = enum + 1
nop
nop
nop
endm ; <<<<<<<<<<<
nop
nop
nop
ifdef __HJWASM__
.default
xor eax,eax
.break
endif
MENDSW
@CCCD0:
ret
swproc endp
deleted
Hey nidud,
thank you, that is a priceless info :t
I was not aware of that. Now, 64 bit can run both 32 and 64 bit.
However, 32 bit has still problem with /Zi
here is a part of the source:
Quoteif (ModuleInfo.Ofssize == USE64){
AddLineQueueX("mov r8d,eax");
AddLineQueueX("mov r10d,%d", casen - 1);//int high = len - 1;
AddLineQueueX("xor r9d,r9d");//int low = 0;
AddLineQueueX("lea r11,%s", GetLabelStr(hll->labels[LDATA2], buff));//int pcases
AddLineQueueX("test r10d,r10d");//while (low <= high) {
AddLineQueueX("js %s", GetLabelStr(hll->labels[LDEF], buff));
}
else{
AddLineQueueX("push ebx");
AddLineQueueX("push esi");
AddLineQueueX("push edi");
AddLineQueueX("mov esi,eax");
AddLineQueueX("mov ebx,%d", casen - 1);//int high = len - 1;
AddLineQueueX("xor ecx,ecx");//int low = 0;
AddLineQueueX("lea edi,%s", GetLabelStr(hll->labels[LDATA2], buff));//int pcases
AddLineQueueX("test ebx,ebx");//while (low <= high) {
AddLineQueueX("js %s", GetLabelStr(hll->labels[LDEF], buff));
}
The atached 64 bit can handle both 32 and 64 bit
here is an example for 32 bit:
Quote;--- Win32 "hello world" console application.
;--- assemble: HJWasm -coff Win32_1.ASM
;--- link: JWlink format win pe file Win32_1.OBJ lib kernel32.lib
;--- or, linking with MS link:
;--- link Win32_1.obj kernel32.lib
.386
.MODEL FLAT, stdcall
option casemap:none
;option DOTNAME
STD_OUTPUT_HANDLE equ -11
WriteConsoleA proto :dword, :dword, :dword, :dword, :dword
GetStdHandle proto :dword
ExitProcess proto :dword
.CONST
string db 13,10,"hello, world.",13,10
.CODE
main proc c
local dwWritten:dword
local hConsole:dword
int 3
mov eax,'ABCF'
.switch eax
.case 'ABCD'
.case 'BCDE'
.case 'ABCC'
mov edx,'ABCG'
.break
.case 'ABCF'
mov edx,'ABCF'
.break
.case 'ABCI'
mov edx,'ABCI'
.break
.case 'ABCJ'
mov edx,'ABCJ'
.break
.default
mov edx,0
.break
.endswitch
mov eax,280
.switch eax
.case 273
mov edx,273
.break
.case 280
mov edx,280
.break
.case 275
mov edx,275
.break
.default
mov edx,0
.break
.endswitch
mov eax,252
.switch eax
.case 273
mov edx,273
.break
.case 280
mov edx,280
.break
.case 252
mov edx,252
.break
.case 274
mov edx,274
.break
.case 277
mov edx,277
.break
.case 281
mov edx,281
.break
.case 269
mov edx,269
.break
.case 282
mov edx,282
.break
.case 283
mov edx,283
.break
.case 286
mov edx,286
.break
.case 287
mov edx,287
.break
.case 289
mov edx,289
.break
.case 290
mov edx,290
.break
.case 291
mov edx,291
.break
.case 292
mov edx,292
.break
.case 293
mov edx,293
.break
.case 294
mov edx,294
.break
.case 295
mov edx,295
.break
.case 296
mov edx,296
.break
.case 274
mov edx,274
.break
.default
mov edx,0
.break
.endswitch
mov eax,280
.switch eax
.case 273
mov edx,273
.break
.case 280
mov edx,280
.break
.case 275
mov edx,275
.break
.default
mov edx,0
.break
.endswitch
mov eax,252
.switch eax
.case 2
mov edx,2
.break
.case 280
mov edx,280
.break
.case 252
mov edx,252
.break
.case 274
mov edx,274
.break
.case 277
mov edx,277
.break
.case 281
mov edx,281
.break
.case 269
mov edx,269
.break
.case 282
mov edx,282
.break
.case 283
mov edx,283
.break
.case 286
mov edx,286
.break
.default
mov edx,0
.break
.endswitch
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hConsole,eax
invoke WriteConsoleA, hConsole, addr string, sizeof string, addr dwWritten, 0
xor eax,eax
ret
main endp
;--- entry
mainCRTStartup proc c
invoke main
invoke ExitProcess, eax
mainCRTStartup endp
END mainCRTStartup
and here is debugger output:
Quote
0019101B CC int 3
0019101C 55 push ebp
0019101D 8B EC mov ebp,esp
0019101F 83 EC 08 sub esp,8
00191022 CC int 3
00191023 B8 46 43 42 41 mov eax,41424346h
00191028 EB 2C jmp 00191056
0019102A BA 47 43 42 41 mov edx,41424347h
0019102F E9 98 00 00 00 jmp 001910CC
00191034 BA 46 43 42 41 mov edx,41424346h
00191039 E9 8E 00 00 00 jmp 001910CC
0019103E BA 49 43 42 41 mov edx,41424349h
00191043 E9 84 00 00 00 jmp 001910CC
00191048 BA 4A 43 42 41 mov edx,4142434Ah
0019104D EB 7D jmp 001910CC
0019104F BA 00 00 00 00 mov edx,0
00191054 EB 76 jmp 001910CC
00191056 53 push ebx
00191057 56 push esi
00191058 57 push edi
00191059 8B F0 mov esi,eax
0019105B BB 05 00 00 00 mov ebx,5
00191060 33 C9 xor ecx,ecx
00191062 8D 3D B4 10 19 00 lea edi,ds:[1910B4h]
00191068 85 DB test ebx,ebx
0019106A 78 E3 js 0019104F
0019106C 8D 04 0B lea eax,[ebx+ecx]
0019106F 99 cdq
00191070 2B C2 sub eax,edx
00191072 D1 F8 sar eax,1
00191074 39 34 87 cmp dword ptr [edi+eax*4],esi
00191077 74 07 je 00191080
00191079 7D 11 jge 0019108C
0019107B 8D 48 01 lea ecx,[eax+1]
0019107E EB 0F jmp 0019108F
00191080 8D 15 98 10 19 00 lea edx,ds:[191098h]
00191086 5F pop edi
00191087 5E pop esi
00191088 5B pop ebx
00191089 FF 24 82 jmp dword ptr [edx+eax*4]
0019108C 8D 58 FF lea ebx,[eax-1]
0019108F 3B CB cmp ecx,ebx
00191091 7E D9 jle 0019106C
00191093 5F pop edi
00191094 5E pop esi
00191095 5B pop ebx
00191096 EB B7 jmp 0019104F
00191098 2A 10 sub dl,byte ptr [eax]
0019109A 19 00 sbb dword ptr [eax],eax
0019109C 2A 10 sub dl,byte ptr [eax]
0019109E 19 00 sbb dword ptr [eax],eax
001910A0 34 10 xor al,10h
001910A2 19 00 sbb dword ptr [eax],eax
001910A4 3E 10 19 adc byte ptr ds:[ecx],bl
001910A7 00 48 10 add byte ptr [eax+10h],cl
001910AA 19 00 sbb dword ptr [eax],eax
001910AC 2A 10 sub dl,byte ptr [eax]
001910AE 19 00 sbb dword ptr [eax],eax
001910B0 4F dec edi
001910B1 10 19 adc byte ptr [ecx],bl
001910B3 00 43 43 add byte ptr [ebx+43h],al
001910B6 42 inc edx
001910B7 41 inc ecx
001910B8 44 inc esp
001910B9 43 inc ebx
001910BA 42 inc edx
001910BB 41 inc ecx
001910BC 46 inc esi
001910BD 43 inc ebx
001910BE 42 inc edx
001910BF 41 inc ecx
001910C0 49 dec ecx
001910C1 43 inc ebx
001910C2 42 inc edx
001910C3 41 inc ecx
001910C4 4A dec edx
001910C5 43 inc ebx
001910C6 42 inc edx
001910C7 41 inc ecx
001910C8 45 inc ebp
001910C9 44 inc esp
001910CA 43 inc ebx
001910CB 42 inc edx
001910CC B8 18 01 00 00 mov eax,118h
001910D1 EB 1C jmp 001910EF
001910D3 BA 11 01 00 00 mov edx,111h
001910D8 EB 2C jmp 00191106
001910DA BA 18 01 00 00 mov edx,118h
001910DF EB 25 jmp 00191106
001910E1 BA 13 01 00 00 mov edx,113h
001910E6 EB 1E jmp 00191106
001910E8 BA 00 00 00 00 mov edx,0
001910ED EB 17 jmp 00191106
001910EF 3D 11 01 00 00 cmp eax,111h
001910F4 74 DD je 001910D3
001910F6 3D 18 01 00 00 cmp eax,118h
001910FB 74 DD je 001910DA
001910FD 3D 13 01 00 00 cmp eax,113h
00191102 74 DD je 001910E1
00191104 EB E2 jmp 001910E8
00191106 B8 FC 00 00 00 mov eax,0FCh
0019110B E9 D2 00 00 00 jmp 001911E2
00191110 BA 11 01 00 00 mov edx,111h
00191115 E9 6A 01 00 00 jmp 00191284
0019111A BA 18 01 00 00 mov edx,118h
0019111F E9 60 01 00 00 jmp 00191284
00191124 BA FC 00 00 00 mov edx,0FCh
00191129 E9 56 01 00 00 jmp 00191284
0019112E BA 12 01 00 00 mov edx,112h
00191133 E9 4C 01 00 00 jmp 00191284
00191138 BA 15 01 00 00 mov edx,115h
0019113D E9 42 01 00 00 jmp 00191284
00191142 BA 19 01 00 00 mov edx,119h
00191147 E9 38 01 00 00 jmp 00191284
0019114C BA 0D 01 00 00 mov edx,10Dh
00191151 E9 2E 01 00 00 jmp 00191284
00191156 BA 1A 01 00 00 mov edx,11Ah
0019115B E9 24 01 00 00 jmp 00191284
00191160 BA 1B 01 00 00 mov edx,11Bh
00191165 E9 1A 01 00 00 jmp 00191284
0019116A BA 1E 01 00 00 mov edx,11Eh
0019116F E9 10 01 00 00 jmp 00191284
00191174 BA 1F 01 00 00 mov edx,11Fh
00191179 E9 06 01 00 00 jmp 00191284
0019117E BA 21 01 00 00 mov edx,121h
00191183 E9 FC 00 00 00 jmp 00191284
00191188 BA 22 01 00 00 mov edx,122h
0019118D E9 F2 00 00 00 jmp 00191284
00191192 BA 23 01 00 00 mov edx,123h
00191197 E9 E8 00 00 00 jmp 00191284
0019119C BA 24 01 00 00 mov edx,124h
001911A1 E9 DE 00 00 00 jmp 00191284
001911A6 BA 25 01 00 00 mov edx,125h
001911AB E9 D4 00 00 00 jmp 00191284
001911B0 BA 26 01 00 00 mov edx,126h
001911B5 E9 CA 00 00 00 jmp 00191284
001911BA BA 27 01 00 00 mov edx,127h
001911BF E9 C0 00 00 00 jmp 00191284
001911C4 BA 28 01 00 00 mov edx,128h
001911C9 E9 B6 00 00 00 jmp 00191284
001911CE BA 12 01 00 00 mov edx,112h
001911D3 E9 AC 00 00 00 jmp 00191284
001911D8 BA 00 00 00 00 mov edx,0
001911DD E9 A2 00 00 00 jmp 00191284
001911E2 3D 28 01 00 00 cmp eax,128h
001911E7 77 EF ja 001911D8
001911E9 2D FC 00 00 00 sub eax,0FCh
001911EE 72 E8 jb 001911D8
001911F0 8D 15 57 12 19 00 lea edx,ds:[191257h]
001911F6 0F B6 04 10 movzx eax,byte ptr [eax+edx]
001911FA 8D 15 03 12 19 00 lea edx,ds:[191203h]
00191200 FF 24 82 jmp dword ptr [edx+eax*4]
00191203 24 11 and al,11h
00191205 19 00 sbb dword ptr [eax],eax
00191207 4C dec esp
00191208 11 19 adc dword ptr [ecx],ebx
0019120A 00 10 add byte ptr [eax],dl
0019120C 11 19 adc dword ptr [ecx],ebx
0019120E 00 2E add byte ptr [esi],ch
00191210 11 19 adc dword ptr [ecx],ebx
00191212 00 CE add dh,cl
00191214 11 19 adc dword ptr [ecx],ebx
00191216 00 38 add byte ptr [eax],bh
00191218 11 19 adc dword ptr [ecx],ebx
0019121A 00 1A add byte ptr [edx],bl
0019121C 11 19 adc dword ptr [ecx],ebx
0019121E 00 42 11 add byte ptr [edx+11h],al
00191221 19 00 sbb dword ptr [eax],eax
00191223 56 push esi
00191224 11 19 adc dword ptr [ecx],ebx
00191226 00 60 11 add byte ptr [eax+11h],ah
00191229 19 00 sbb dword ptr [eax],eax
0019122B 6A 11 push 11h
0019122D 19 00 sbb dword ptr [eax],eax
0019122F 74 11 je 00191242
00191231 19 00 sbb dword ptr [eax],eax
00191233 7E 11 jle 00191246
00191235 19 00 sbb dword ptr [eax],eax
00191237 88 11 mov byte ptr [ecx],dl
00191239 19 00 sbb dword ptr [eax],eax
0019123B 92 xchg eax,edx
0019123C 11 19 adc dword ptr [ecx],ebx
0019123E 00 9C 11 19 00 A6 11 add byte ptr [ecx+edx+11A60019h],bl
00191245 19 00 sbb dword ptr [eax],eax
00191247 B0 11 mov al,11h
00191249 19 00 sbb dword ptr [eax],eax
0019124B BA 11 19 00 C4 mov edx,0C4001911h
00191250 11 19 adc dword ptr [ecx],ebx
00191252 00 D8 add al,bl
00191254 11 19 adc dword ptr [ecx],ebx
00191256 00 00 add byte ptr [eax],al
00191258 14 14 adc al,14h
0019125A 14 14 adc al,14h
0019125C 14 14 adc al,14h
0019125E 14 14 adc al,14h
00191260 14 14 adc al,14h
00191262 14 14 adc al,14h
00191264 14 14 adc al,14h
00191266 14 14 adc al,14h
00191268 01 14 14 add dword ptr [esp+edx],edx
0019126B 14 02 adc al,2
0019126D 03 04 14 add eax,dword ptr [esp+edx]
00191270 05 14 14 06 07 add eax,7061414h
00191275 08 09 or byte ptr [ecx],cl
00191277 14 14 adc al,14h
00191279 0A 0B or cl,byte ptr [ebx]
0019127B 14 0C adc al,0Ch
0019127D 0D 0E 0F 10 11 or eax,11100F0Eh
00191282 12 13 adc dl,byte ptr [ebx]
00191284 B8 18 01 00 00 mov eax,118h
00191289 EB 1C jmp 001912A7
0019128B BA 11 01 00 00 mov edx,111h
00191290 EB 2C jmp 001912BE
00191292 BA 18 01 00 00 mov edx,118h
00191297 EB 25 jmp 001912BE
00191299 BA 13 01 00 00 mov edx,113h
0019129E EB 1E jmp 001912BE
001912A0 BA 00 00 00 00 mov edx,0
001912A5 EB 17 jmp 001912BE
001912A7 3D 11 01 00 00 cmp eax,111h
001912AC 74 DD je 0019128B
001912AE 3D 18 01 00 00 cmp eax,118h
001912B3 74 DD je 00191292
001912B5 3D 13 01 00 00 cmp eax,113h
001912BA 74 DD je 00191299
001912BC EB E2 jmp 001912A0
001912BE B8 FC 00 00 00 mov eax,0FCh
001912C3 EB 6E jmp 00191333
001912C5 BA 02 00 00 00 mov edx,2
001912CA E9 FA 00 00 00 jmp 001913C9
001912CF BA 18 01 00 00 mov edx,118h
001912D4 E9 F0 00 00 00 jmp 001913C9
001912D9 BA FC 00 00 00 mov edx,0FCh
001912DE E9 E6 00 00 00 jmp 001913C9
001912E3 BA 12 01 00 00 mov edx,112h
001912E8 E9 DC 00 00 00 jmp 001913C9
001912ED BA 15 01 00 00 mov edx,115h
001912F2 E9 D2 00 00 00 jmp 001913C9
001912F7 BA 19 01 00 00 mov edx,119h
001912FC E9 C8 00 00 00 jmp 001913C9
00191301 BA 0D 01 00 00 mov edx,10Dh
00191306 E9 BE 00 00 00 jmp 001913C9
0019130B BA 1A 01 00 00 mov edx,11Ah
00191310 E9 B4 00 00 00 jmp 001913C9
00191315 BA 1B 01 00 00 mov edx,11Bh
0019131A E9 AA 00 00 00 jmp 001913C9
0019131F BA 1E 01 00 00 mov edx,11Eh
00191324 E9 A0 00 00 00 jmp 001913C9
00191329 BA 00 00 00 00 mov edx,0
0019132E E9 96 00 00 00 jmp 001913C9
00191333 53 push ebx
00191334 56 push esi
00191335 57 push edi
00191336 8B F0 mov esi,eax
00191338 BB 09 00 00 00 mov ebx,9
0019133D 33 C9 xor ecx,ecx
0019133F 8D 3D A1 13 19 00 lea edi,ds:[1913A1h]
00191345 85 DB test ebx,ebx
00191347 78 E0 js 00191329
00191349 8D 04 0B lea eax,[ebx+ecx]
0019134C 99 cdq
0019134D 2B C2 sub eax,edx
0019134F D1 F8 sar eax,1
00191351 39 34 87 cmp dword ptr [edi+eax*4],esi
00191354 74 07 je 0019135D
00191356 7D 11 jge 00191369
00191358 8D 48 01 lea ecx,[eax+1]
0019135B EB 0F jmp 0019136C
0019135D 8D 15 75 13 19 00 lea edx,ds:[191375h]
00191363 5F pop edi
00191364 5E pop esi
00191365 5B pop ebx
00191366 FF 24 82 jmp dword ptr [edx+eax*4]
00191369 8D 58 FF lea ebx,[eax-1]
0019136C 3B CB cmp ecx,ebx
0019136E 7E D9 jle 00191349
00191370 5F pop edi
00191371 5E pop esi
00191372 5B pop ebx
00191373 EB B4 jmp 00191329
00191375 C5 12 lds edx,fword ptr [edx]
00191377 19 00 sbb dword ptr [eax],eax
00191379 D9 12 fst dword ptr [edx]
0019137B 19 00 sbb dword ptr [eax],eax
0019137D 01 13 add dword ptr [ebx],edx
0019137F 19 00 sbb dword ptr [eax],eax
00191381 E3 12 jecxz 00191395
00191383 19 00 sbb dword ptr [eax],eax
00191385 ED in eax,dx
00191386 12 19 adc bl,byte ptr [ecx]
00191388 00 CF add bh,cl
0019138A 12 19 adc bl,byte ptr [ecx]
0019138C 00 F7 add bh,dh
0019138E 12 19 adc bl,byte ptr [ecx]
00191390 00 0B add byte ptr [ebx],cl
00191392 13 19 adc ebx,dword ptr [ecx]
00191394 00 15 13 19 00 1F add byte ptr ds:[1F001913h],dl
0019139A 13 19 adc ebx,dword ptr [ecx]
0019139C 00 29 add byte ptr [ecx],ch
0019139E 13 19 adc ebx,dword ptr [ecx]
001913A0 00 02 add byte ptr [edx],al
001913A2 00 00 add byte ptr [eax],al
001913A4 00 FC add ah,bh
001913A6 00 00 add byte ptr [eax],al
001913A8 00 0D 01 00 00 12 add byte ptr ds:[12000001h],cl
001913AE 01 00 add dword ptr [eax],eax
001913B0 00 15 01 00 00 18 add byte ptr ds:[18000001h],dl
001913B6 01 00 add dword ptr [eax],eax
001913B8 00 19 add byte ptr [ecx],bl
001913BA 01 00 add dword ptr [eax],eax
001913BC 00 1A add byte ptr [edx],bl
001913BE 01 00 add dword ptr [eax],eax
001913C0 00 1B add byte ptr [ebx],bl
001913C2 01 00 add dword ptr [eax],eax
001913C4 00 1E add byte ptr [esi],bl
001913C6 01 00 add dword ptr [eax],eax
001913C8 00 6A F5 add byte ptr [edx-0Bh],ch
001913CB E8 4C 10 00 00 call 0019241C
001913D0 89 45 F8 mov dword ptr [ebp-8],eax
001913D3 6A 00 push 0
001913D5 8D 45 FC lea eax,[ebp-4]
001913D8 50 push eax
001913D9 6A 11 push 11h
001913DB 68 00 40 19 00 push 194000h
001913E0 FF 75 F8 push dword ptr [ebp-8]
001913E3 E8 2E 10 00 00 call 00192416
001913E8 33 C0 xor eax,eax
001913EA C9 leave
001913EB C3 ret
001913EC E8 2B FC FF FF call 0019101C
001913F1 50 push eax
001913F2 E8 2B 10 00 00 call 00192422
001913F7 CC int 3
So, I found out that this is not fault in the .SWITCH but any 32 bit
I have build wit without /Zi and Linked with DEBUG option and it does job properly,
However, something is wrong with line numbers.
It is hard to find out what is wrong because 64 bit works fine with /Zi option
I will need some more time to figure it out
Hi habran!
If you are working in 64 bit, I think there is no gain in solve the 32 bit issue, just the challenge (perhaps some future boring time).
In the example code I see some opcodes I don't see in hll.c HJWAsm source (AAM). Apparenty there is some kind of displacement ¿in .endswitch? and perhaps directions became opcodes.
00401060 57 PUSH EDI
00401061 8BF0 MOV ESI,EAX
00401063 BB 05000000 MOV EBX,5
00401068 33C9 XOR ECX,ECX
0040106A 8D3D BC104000 LEA EDI,DWORD PTR DS:[4010BC]
00401070 85DB TEST EBX,EBX
00401072 ^78 E3 JS SHORT hab1c.00401057
00401074 8D040B LEA EAX,DWORD PTR DS:[EBX+ECX]
00401077 99 CDQ
00401078 2BC2 SUB EAX,EDX
0040107A D1F8 SAR EAX,1
0040107C 393487 CMP DWORD PTR DS:[EDI+EAX*4],ESI
0040107F 74 07 JE SHORT hab1c.00401088
00401081 7D 11 JGE SHORT hab1c.00401094
00401083 8D48 01 LEA ECX,DWORD PTR DS:[EAX+1]
00401086 EB 0F JMP SHORT hab1c.00401097
00401088 8D15 A0104000 LEA EDX,DWORD PTR DS:[4010A0]
0040108E 5F POP EDI
0040108F 5E POP ESI
00401090 5B POP EBX
00401091 FF2482 JMP DWORD PTR DS:[EDX+EAX*4]
00401094 8D58 FF LEA EBX,DWORD PTR DS:[EAX-1]
00401097 3BCB CMP ECX,EBX
00401099 ^7E D9 JLE SHORT hab1c.00401074
0040109B 5F POP EDI
0040109C 5E POP ESI
0040109D 5B POP EBX
0040109E ^EB B7 JMP SHORT hab1c.00401057 <<< last correct line
004010A0 D4 10 AAM 10
004010A2 40 INC EAX
004010A3 00D4 ADD AH,DL
004010A5 1040 00 ADC BYTE PTR DS:[EAX],AL
004010A8 D4 10 AAM 10
004010AA 40 INC EAX
004010AB 00D4 ADD AH,DL
004010AD 1040 00 ADC BYTE PTR DS:[EAX],AL
004010B0 D4 10 AAM 10
004010B2 40 INC EAX
004010B3 00D4 ADD AH,DL
004010B5 1040 00 ADC BYTE PTR DS:[EAX],AL
004010B8 57 PUSH EDI
004010B9 1040 00 ADC BYTE PTR DS:[EAX],AL
004010BC 17 POP SS ; Modification of segment register
004010BD FB STI
004010BE F3: PREFIX REP: ; Superfluous prefix
004010BF FF21 JMP DWORD PTR DS:[ECX]
004010C1 FB STI
004010C2 F3: PREFIX REP: ; Superfluous prefix
004010C3 FF35 FBF3FF53 PUSH DWORD PTR DS:[53FFF3FB]
004010C9 FB STI
004010CA F3: PREFIX REP: ; Superfluous prefix
004010CB FF5D FB CALL FAR FWORD PTR SS:[EBP-5] ; Far call
004010CE F3: PREFIX REP: ; Superfluous prefix
004010CF FF87 26F4FFCC INC DWORD PTR DS:[EDI+CCFFF426]
<<<< Here I put INT 3 ¿where is my line?
Added to previous instruccion
004010D5 50 PUSH EAX
004010D6 58 POP EAX
004010D7 CC INT3
Quote from: HSE on April 17, 2016, 03:28:14 AM0040109E ^EB B7 JMP SHORT hab1c.00401057 <<< last correct line
004010A0 D4 10 AAM 10
004010A2 40 INC EAX
004010A3 00D4 ADD AH,DL
004010A5 1040 00 ADC BYTE PTR DS:[EAX],AL
004010A8 D4 10 AAM 10
004010AA 40 INC EAX
004010AB 00D4 ADD AH,DL
004010AD 1040 00 ADC BYTE PTR DS:[EAX],AL
004010B0 D4 10 AAM 10
004010B2 40 INC EAX
004010B3 00D4 ADD AH,DL
004010B5 1040 00 ADC BYTE PTR DS:[EAX],AL
004010B8 57 PUSH EDI
004010B9 1040 00 ADC BYTE PTR DS:[EAX],AL
In case you are working with Olly: select these lines, then hit Ctrl A (a like analysis). You will see that these are addresses, e.g. 00 40 10 D4
Thanks JJ2007, yes that are jump addresses, but debugger doesn't know that and is trying to convert numbers to codes.
HSE, I do programming only in 64 bit and that is why I was not aware that since the first HJWasm /Zi doesn't work for 32 bit.
I know that most of the people who still do programming in 32 bit use Olly for debugging and they don't care about source level debugging, however, it puzzles me what is causing that problem.
For now, I will leave it as it is because it works as expected except the debug info.
If you link with DEBUG option it actually creates debug info except the line numbers. here is how it looks like:
Quote008E1004 CC int 3
_mainCRTStartup:
008E1005 E9 D2 02 00 00 jmp _mainCRTStartup (08E12DCh)
_main:
008E100A E9 11 00 00 00 jmp _main (08E1020h)
008E100F CC int 3
008E1010 CC int 3
008E1011 CC int 3
008E1012 CC int 3
008E1013 CC int 3
008E1014 CC int 3
008E1015 CC int 3
008E1016 CC int 3
008E1017 CC int 3
008E1018 CC int 3
008E1019 CC int 3
008E101A CC int 3
008E101B CC int 3
008E101C CC int 3
008E101D CC int 3
008E101E CC int 3
008E101F CC int 3
_main:
008E1020 55 push ebp
008E1021 8B EC mov ebp,esp
008E1023 83 EC 08 sub esp,8
008E1026 CC int 3
008E1027 B8 46 43 42 41 mov eax,41424346h
008E102C EB 2C jmp _main+3Ah (08E105Ah)
008E102E BA 47 43 42 41 mov edx,41424347h
008E1033 E9 98 00 00 00 jmp _main+0B0h (08E10D0h)
008E1038 BA 46 43 42 41 mov edx,41424346h
008E103D E9 8E 00 00 00 jmp _main+0B0h (08E10D0h)
008E1042 BA 49 43 42 41 mov edx,41424349h
008E1047 E9 84 00 00 00 jmp _main+0B0h (08E10D0h)
008E104C BA 4A 43 42 41 mov edx,4142434Ah
008E1051 EB 7D jmp _main+0B0h (08E10D0h)
008E1053 BA 00 00 00 00 mov edx,0
008E1058 EB 76 jmp _main+0B0h (08E10D0h)
We will just upload a fixed version to teraspace
Thanks JJ! Olly read your post because now open in that mode. I suspected they were addresses, and there is no addresses in that place in habran code.
Thanks habran! I was just been curious. Perhaps comparing the debug that you posted with mine, something became more clear... but not! :dazzled:
Here is an example how C compiler handles switch, that will make it more clear to you
HJWasm does it very similar except it has to create addresses 64 bit for x64 code
static const char *size_name(int size)
{
switch (size) {
case 1:
return "byte";
case 2:
return "word";
case 4:
return "dword";
case 8:
return "qword";
case 10:
return "tword";
case 16:
return "oword";
case 32:
return "yword";
case 64:
return "zword";
default:
return "???";
}
}
size_name PROC
; 266 : switch (size) {
dec ecx
cmp ecx, 63 ; 0000003fH
ja SHORT $LN1@size_name
lea rdx, OFFSET FLAT:__ImageBase
movsxd rax, ecx
movzx eax, BYTE PTR $LN14@size_name[rdx+rax]
mov ecx, DWORD PTR $LN15@size_name[rdx+rax*4]
add rcx, rdx
jmp rcx
$LN9@size_name:
; 267 : case 1:
; 268 : return "byte";
lea rax, OFFSET FLAT:$SG8672
; 285 : }
; 286 : }
ret 0
$LN8@size_name:
; 269 : case 2:
; 270 : return "word";
lea rax, OFFSET FLAT:$SG8674
; 285 : }
; 286 : }
ret 0
$LN7@size_name:
; 271 : case 4:
; 272 : return "dword";
lea rax, OFFSET FLAT:$SG8676
; 285 : }
; 286 : }
ret 0
$LN6@size_name:
; 273 : case 8:
; 274 : return "qword";
lea rax, OFFSET FLAT:$SG8678
; 285 : }
; 286 : }
ret 0
$LN5@size_name:
; 275 : case 10:
; 276 : return "tword";
lea rax, OFFSET FLAT:$SG8680
; 285 : }
; 286 : }
ret 0
$LN4@size_name:
; 277 : case 16:
; 278 : return "oword";
lea rax, OFFSET FLAT:$SG8682
; 285 : }
; 286 : }
ret 0
$LN3@size_name:
; 279 : case 32:
; 280 : return "yword";
lea rax, OFFSET FLAT:$SG8684
; 285 : }
; 286 : }
ret 0
$LN2@size_name:
; 281 : case 64:
; 282 : return "zword";
lea rax, OFFSET FLAT:$SG8686
; 285 : }
; 286 : }
ret 0
$LN1@size_name:
; 283 : default:
; 284 : return "???";
lea rax, OFFSET FLAT:$SG8688
; 285 : }
; 286 : }
ret 0
npad 3
$LN15@size_name:
DD $LN9@size_name
DD $LN8@size_name
DD $LN7@size_name
DD $LN6@size_name
DD $LN5@size_name
DD $LN4@size_name
DD $LN3@size_name
DD $LN2@size_name
DD $LN1@size_name
$LN14@size_name:
DB 0
DB 1
DB 8
DB 2
DB 8
DB 8
DB 8
DB 3
DB 8
DB 4
DB 8
DB 8
DB 8
DB 8
DB 8
DB 5
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 6
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 8
DB 7
size_name ENDP
Quote from: habran on April 17, 2016, 06:11:41 AMHSE, I do programming only in 64 bit and that is why I was not aware that since the first HJWasm /Zi doesn't work for 32 bit.
I know that most of the people who still do programming in 32 bit use Olly for debugging and they don't care about source level debugging
Source level debugging is possible with Olly, but with macros it makes little sense. Most people would use
symbolic debugging, though, and that works with HJWasm32 (version 11 April):
include \masm32\MasmBasic\MasmBasic.inc ; download (http://masm32.com/board/index.php?topic=94.0)
.data
MyQ QWORD 1234567812345678h
Init
int 3
Print Str$("The value is %i\n", MyQ)
Inkey "Assembler used: ", AsmUsed$()
EndOfCode0040107C ³. CC int3
0040107D ³. 8D05 00704000 lea eax, [MyQ]
00401083 ³. 50 push eax
00401084 ³. 6A 05 push 5
00401086 ³. 6A 30 push 30
00401088 ³. 68 58704000 push offset ra_lbl2 ; ASCII "The value is %i\n"
0040108D ³. E8 04020000 call Float2Asc
00401092 ³. 6A 7F push 7F
00401094 ³. 6A 01 push 1
00401096 ³. E8 38100000 call MbPrint
0040109B ³. 68 6C704000 push offset ra_lbl3 ; ASCII "Assembler used: "
004010A0 ³. 68 80704000 push offset ra_lbl4 ; ASCII "HJWasm32"
004010A5 ³. 6A 22 push 22
004010A7 ³. E8 27100000 call MbPrint
I know now for certain that these two lines in 32 bit cause general failure error but why only in 32 bit and why they still create proper code, I have no idea
I wish that someone enlighten me
Quote
if (ModuleInfo.Ofssize == USE64){
AddLineQueueX("lea rdx,%s", GetLabelStr(hll->labels[LDATA2], buff));this is OK
AddLineQueueX("movzx rax,BYTE PTR[rdx+rax]");
AddLineQueueX("lea rdx,%s", GetLabelStr(hll->labels[LDATA1], buff));this is OK
AddLineQueueX("jmp QWORD PTR[rdx+rax*8]");
}
else{
AddLineQueueX("lea edx,%s", GetLabelStr(hll->labels[LDATA2], buff)); ERROR
AddLineQueueX("movzx eax,BYTE PTR[edx+eax]");
AddLineQueueX("lea edx,%s", GetLabelStr(hll->labels[LDATA1], buff));ERROR
AddLineQueueX("jmp DWORD PTR[edx+eax*4]");
}
They look identical. How is the general failure triggered? SEH? Switch it off and let it crash...
Maybe double check to see what is in ModuleInfo.Ofssize if it is != USE64, as in the branch that fails, double check to see its not some other value relevant to 16bit or some other definition that is the same as 64bit. Might explain the crashing then if some other value is passed and your assuming its for 32bit where in fact it might be still related to 64bit code? dunno if that makes sense, but hopefully verifying what is in ModuleInfo.Ofssize might help
Thanks fearless, :biggrin:
I tried that already but did not help :(
You have a compiler that spits out "general failure". There must be code that ends up in the line printf("general failure"). Find out at which point the code jumps there. Insert a printf("error code=%i", retval), or an INT 3.
My best guess is it's an exception handler. Exception handlers can be commented out or switched off, and your just-in-time debugger will tell you precisely where the exception happens.
Btw it would help to have a short example of code failing with "general failure", together with the settings used (/Zi? /Zf?) with a link to the exact HJWasmxxx version that can't handle that code. Right now I've tried a lot but can't convince HJWasm32.exe to shout "general failure".
Hi JJ2007,
This attached folder contains the source and HJWasm32
If you build with /Zi or /Zd it will throw the General Failure error
This is a debug version of HJWasm
release version throws the same error even if you not build with /Zi
Let see if you can find why
Keep in mind that 64 bite works fine, that means that somewhere data is misinterpreted
The bug is here in linnum.c line 58 but what causes it is a question:
First-chance exception at 0x010593AB in HJWasm.exe: 0xC0000005: Access violation writing location 0x00FEEB04.
Unhandled exception at 0x010593AB in HJWasm.exe: 0xC0000005: Access violation writing location 0x00FEEB04.
Quote
static void AddLinnumData( struct line_num_info *data )
/*****************************************************/
{
struct qdesc *q;
#if COFF_SUPPORT
if ( Options.output_format == OFORMAT_COFF ) {
q = (struct qdesc *)CurrSeg->e.seginfo->LinnumQueue;
if ( q == NULL ) {
q = LclAlloc( sizeof( struct qdesc ) );
CurrSeg->e.seginfo->LinnumQueue = q;
q->head = NULL;
}
} else
#endif
q = &LinnumQueue;
data->next = NULL;
if ( q->head == NULL)
q->head = q->tail = data;
else {
((struct line_num_info *)q->tail)->next = data; // here is the bug
q->tail = data;
}
}
Quote from: habran on April 18, 2016, 08:40:09 PMThis is a debug version of HJWasm
Unfortunately, it won't run on Win7-64 - msvcrt120d.dll missing...
One debugging technique that I use often in bigger packages is to use a global variable to break. In assembler code:
.if globaldebug==123
mov globaldebug, 0 ; use the flag only once
INT 3 ; allow JIT debugger to break here
.endif
Then, in the source, you use mov globaldebug, 123 before the region where you suspect the problem. For example, if you know the general failure happens here:
mov eax,'ABCF'
NoP ; hijack the nop handler
.switch eax
.case 'ABCC' ; <<<< it happens here
mov edx,'ABCG'
.break... then use a
globaldebug=123; where you handle the nop instruction, if and only if the case-sensitive nop happens to be NoP (which no sane coder would use).
Should be possible in C. The bug looks like a de-referencing problem, but I am no good at C, and can't see the q/tail/next etc structure either. Btw isn't
next a reserved word?
P.S.: Under the hood...
asm("int $3");
((struct line_num_info *)q->tail)->next = data;
asm("nop");
q->tail = data;
asm("nop");
00428A54 ³. CC int3
00428A55 ³. 8B43 04 mov eax, [ebx+4]
00428A58 ³. 8930 mov [eax], esi
00428A5A ³. 90 nop
00428A5B ³. 8973 04 mov [ebx+4], esi <<<<<<<<< CRASH
00428A5E ³. 90 nop
Thank you JJ for such a detailed info :t
Actually, in VS debugger I can break in that peace of code and see all variables contests, however, you know from the life experience about the cause and effect: the effect is here but the cause is hiding somewhere else
The cause is what I am looking for :dazzled:
Quote from: habran on April 18, 2016, 11:59:55 PM
The cause is what I am looking for :dazzled:
printf("q=%x\t", q);
printf("q tail=%x\n", q->tail);
((struct line_num_info *)q->tail)->next = data;
q->tail = data;
Result:
...
q=4b0230 q tail=4b0788
q=4b0230 q tail=4b0798
q=4b0230 q tail=4b07a8
q=4b0230 q tail=4b07b8
q=4b0230 q tail=4b07c8
q=4b0230 q tail=4b0700
q=4b0230 q tail=feebe8
4bnnnn looks like heapalloc'ed addresses. The last one, feebe8, is something like BAAD F00D 8)
Yeah, I know that, that is the effect but what is the cause :(
I mean, why is there BAAD F00D???
I think that even 4b0700 is already wrong address, it suppose to be 4b07d8
We have to find the MF diversant (the function) who put it there :badgrin:
How myatoi128() handle that .case 'ABCD' ?
hll.c in GitHub crash after that ?
In debug builds pointer hll is destroyed at some point after myatoi128().
If i put hll = HllStack; after myatoi128() call, i can avoid crash :icon_confused:
or if i move uint_64 n; after int j;:icon_confused:
Hi TWell,
That HJWasm in repository can not handle the 'ABCD' yet, this is a new feature which will be in the next upload
We did not upload it yet because of that /Zi problem in 32 bit
myatoi128 doesn't handle it, this is a routine that does:
we have added at the top of the function 3 additional vars:
uint_64 dst[1];
int a;
uint_8 c;
Quote
j = strlen(buffer);
if (buffer[0] == 0x27){ // 0x27 = ''' EG: 'ABCD'
a = 1; // skip '''
dst[0] = 0; // zero it before use
while (a < j){
c = buffer[a]; // read 1 byte at the time
if (c == 0x27) // ''' ? is it the end
break; // finish
dst[0] <<= 8; // make space for next byte
dst[0] |= c; // add at the end a new char
a++; // increase a counter
}
n = dst[0]; put the result in n variable
}
else if ((buffer[j-1] | 0x20) == 'h' )
myatoi128( buffer, &n, 16, j-1);
#if CHEXPREFIX
else if (((buffer[1] | 0x20)== 'x') && (*buffer == '0'))
myatoi128( buffer, &n, 16, j-2);
#endif
else
myatoi128( buffer, &n, 10, j);
pcases[hll->casecnt] = (int_32)n;
myatoi128( buff+2, &n, 16, 4);
plabels[hll->casecnt] = (uint_16)n;
hll->casecnt++;
break;
linnum.c:
static void AddLinnumData( struct line_num_info *data )
/*****************************************************/
{
struct qdesc *q;
#if COFF_SUPPORT
if ( Options.output_format == OFORMAT_COFF ) {
q = (struct qdesc *)CurrSeg->e.seginfo->LinnumQueue; // the problem seems to be here
if ( q == NULL ) {
q = LclAlloc( sizeof( struct qdesc ) );
CurrSeg->e.seginfo->LinnumQueue = q;
q->head = NULL;
}
} else
#endif
q = 0; // line 51 - insert q=0 so that q is always set by the line below:
q = &LinnumQueue;
This line throws the exception:
((struct line_num_info *)q->tail)->next = data;
Shortly before, q->head changes its value ::)
not surprisingly that that such code blow up in your face: global variables (in a "recursive environment") and names like a,b,... casen, ncase ,...
8)
The lifecycle of pcases and plabesl in hll.c look suspicious (from the github repo)
That is good find JJ :t
Now we have to find why is CurrSeg->e.seginfo->LinnumQueue having wrong data
qWord, I can assure you that problem is not there, I tried to use hll->casen and it has the same problem
If that would be a problem, 64 bit wouldn't work either
I am almost certain that problem comes from coff.c
read from line 1138
A short session with clang's AddressSanitizer...:
- HllExitDir@hll.c: local variable uint64_t n is passed as pointer to myatoi128, but the functions requires an array of two elements.
- memory_operand@parser.c, line 1590 and 1591: index and base are used without checking for EMPTY.
Another problem, as already said, is
pcases/
plabels in
hll.c: Beside that this solution can't work for nested control blocks (at least I can't see the change currently), these variables are tested for null-pointers but never set to zero after freeing.
I would strongly suggest to enable all warnings
/Wall and then selectively disable warnings that (currently) makes no sense to fix. Doing so you can (i.a.) quickly find that the header guard for
types.h is broken.
regards
Hi qWord,
You were right in saying that global variables can't work for nested control blocks, so I have changed it to hll->pcases
and hll->plabels, and that works fine in x64,however, now x86 has got general failure with or without /Zi
have look for yourself
Take with care... :icon_eek:
but Work!! :t
What that means HSE?
See the test. The table has correct addresses now. Of course, all this things with "H".
I am not sure that I understood what you said :dazzled:
can you try to build that:
;--- Win32 "hello world" console application.
;--- assemble: HJWasm -coff Win32_1.ASM
;--- link: JWlink format win pe file Win32_1.OBJ lib kernel32.lib
;--- or, linking with MS link:
;--- link Win32_1.obj kernel32.lib
.486
.MODEL FLAT, stdcall
option casemap:none
;option DOTNAME
STD_OUTPUT_HANDLE equ -11
WriteConsoleA proto :dword, :dword, :dword, :dword, :dword
GetStdHandle proto :dword
ExitProcess proto :dword
.CONST
string db 13,10,"hello, world.",13,10
.CODE
main proc c
local dwWritten:dword
local hConsole:dword
int 3
mov eax,'ABCF'
.switch eax
.case 'ABCD'
.case 'BCDE'
.case 'ABCC'
mov edx,'ABCG'
.break
.case 'ABCF'
mov edx,'ABCF'
.break
.case 'ABCI'
mov edx,'ABCI'
.break
.case 'ABCJ'
mov edx,'ABCJ'
.break
.default
mov edx,0
.break
.endswitch
mov eax,252
.switch eax
.case 2
mov edx,2
.break
.case 280
mov edx,280
.break
.case 252
mov edx,252
.break
.case 274
mov edx,274
.break
.case 277
mov edx,277
.break
.case 281
mov edx,281
.break
.case 269
mov edx,269
.break
.case 282
mov edx,282
.break
.case 283
mov edx,283
.break
.case 286
mov edx,286
.break
.default
mov edx,0
.break
.endswitch
mov eax,252
.switch eax
.case 273
mov edx,273
.break
.case 280
mov edx,280
.break
.case 252
mov edx,252
.break
.case 274
mov edx,274
.break
.case 277
mov edx,277
.break
.case 281
mov edx,281
.break
.case 269
mov edx,269
.break
.case 282
mov edx,282
.break
.case 283
mov edx,283
.break
.case 286
mov edx,286
.break
.default
mov edx,0
.break
.endswitch
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hConsole,eax
invoke WriteConsoleA, hConsole, addr string, sizeof string, addr dwWritten, 0
xor eax,eax
ret
main endp
;--- entry
mainCRTStartup proc c
invoke main
invoke ExitProcess, eax
mainCRTStartup endp
END mainCRTStartup
deleted
habran,
because the collision I have T_DOT_CASEH, .caseh, etc
I'm using link.
>HSE, that looks good and works on my laptop, did you build with /Zi option?
>nidud, I agree with you to some point and I am planing to enhance capabilities to the .switch, I don't agree with you that volatile registers should be preserved ( eax, edx, ecx, r8, r9,r10, r11)
For now here are both release binaries:
the x64 works fine and can create line numbers with /Zi option, that means it can be debugged at source level
the x86 works fine but can not create line numbers, so don't use /Zi option but you can link with DEBUGER
and debug code at code level
Here is x64
Just to let you know, both version are build with Visual Studio Comunity 15
It suppose to work fine because I have built it with /MT option
Let me know if some problems, please.
If you are happy with this we can upload it to the teraspace.
I will take some more time to improve everything, and hopefully find where is code being overwritten with line numbers
deleted
Thanks nidud, I was just going through expraval.c to find the better solution, I wasnot happy with this either.
The hardest thing for me was to set up the base and make it work. Now I am looking how to fine tune it.
You are always giving me a precious tips and I appreciate it very much :bgrin:
When I was working on .for-.endfor I did the same in the first place but than I found the way how to use already existing functions to do that instead.
I will see if I can make it work that way 8)
Hab1.asm (only one switch)
No evident problem with /Zi or /Zd at object compilation.
No problem with usual linking.
Problem linking with /Debug :hab1.obj : error : Internal error during Pass2
ExceptionCode = C0000005
ExceptionFlags = 00000000
ExceptionAddress = 65B01DA0
NumberParameters = 00000002
ExceptionInformation[ 0] = 00000000
ExceptionInformation[ 1] = 362935A9
CONTEXT:
Eax = 362935A1 Esp = 0012F054
Ebx = 00000204 Ebp = 0012F0B0
Ecx = 00000E00 Esi = 0012F070
Edx = 008BEFE8 Edi = 00000002
Eip = 65B01DA0 EFlags = 00010202
SegCs = 0000001B SegDs = 00000023
SegSs = 00000023 SegEs = 00000023
SegFs = 0000003B SegGs = 00000000
Dr0 = 0012F054 Dr3 = 00000204
Dr1 = 0012F0B0 Dr6 = 00000E00
Dr2 = 00000000 Dr7 = 00000000
But here... Win32_1.asm:win32_1.asm(88) : Error A2168: General Failure
It's the line that follow the second .endswitch. Testing only one switch I never see this problem.
Thanks HSE :t
Hi nidud,
I have succeeded to implement EvalOperand() and now we can handle almost everything.
The only thing that is missing is "string", that needs a special handling
Quotecase T_DOT_CASE:
if (hll->cmd != HLL_SWITCH) {
DebugMsg(("HllExitDir stack error\n"));
return(EmitError(DIRECTIVE_MUST_BE_IN_CONTROL_BLOCK));
}
hll->labels[LTEST] = GetHllLabel();
AddLineQueueX("%s" LABELQUAL, GetLabelStr(hll->labels[LTEST], buff));
i++;
if (tokenarray.token != T_FINAL) {
DebugMsg1(("HllExitDir(%s): calling EvalOperand, i=%u\n", tokenarray.string_ptr, i));
if (EvalOperand(&i, tokenarray, Token_Count, &opndx, 0) == ERROR) {
DebugMsg(("HllExitDir(%s): EvalOperand() failed\n", tokenarray.string_ptr));
return(ERROR);
}
i++;
switch (opndx.kind) {
case EXPR_CONST:
tokenarray.token = T_FINAL;
break;
case EXPR_FLOAT:
#if FPIMMEDIATE
if (Options.strict_masm_compat == FALSE) {
/* convert to REAL4, unless REAL8 coercion is requested */
atofloat(&opndx.fvalue, opndx.float_tok->string_ptr, opndx.mem_type == MT_REAL8 ? 8 : 4, opndx.negative, opndx.float_tok->floattype);
tokenarray.token = T_FINAL;
break;
}
#endif
}
}
else {
DebugMsg(("HllExitDir stack error\n"));
return(EmitError(MISSING_OPERATOR_IN_EXPRESSION));
}
if (!hll->pcases) {
if (casen > 56) {
hll->pcases = LclAlloc(sizeof(int) * casen);
hll->plabels = LclAlloc(sizeof(uint_16) * casen);
}
else {
hll->pcases = LclAlloc(sizeof(int) * 56);
hll->plabels = LclAlloc(sizeof(uint_16) * 56);
}
}
hll->pcases[hll->casecnt] = opndx.value;
myatoi128(buff + 2, dst, 16, 4);
n = dst[0];
hll->plabels[hll->casecnt] = (uint_16)n;
hll->casecnt++;
break;
deleted
deleted
You are correct, I was not aware of that.
So, in that case x64 can accept 8 chars as a constant, like:
mov rax, "astrings"
I will see if I can rework x64 to accept eax and rax depending on a constant size.
I still have to make it able to accept 1 or 2 cases.
I am not clear with your last post, what do you mean exactly
deleted
I don't like the idea of using a linked list, it would take more memory as well as slow down everything.
I have already prepared everything for x64 cases and it is not difficult to add one more flag to hll_item (hll->csize)
I am planing to use EvalOperand() in the .SWITCH entry, which will tell me everything abut a parameter.
I am thinking about more sophisticated use of the .SWITCH entry
I have also solved the problem with one or two cases.
I have a great news :t
Not that I succeeded to implement x64 constants, REAL8, "constants", 'ABCD' ...
but I succeeded to fix /Zi for x86 :bgrin:
Now everything works flawlessly 8)
We will upload it tonight or tomorrow, as soon as Johnsa get time to build it all
habran,
There is something I should have added, there is no reason not to have "break" available as it can be used for conditional exit to the next level down. A modernised "switch" is clean and tidy but if in one "case" statement there is a conditional test where one option is to exit the current level switch block, break is a clean and tidy way to do it. In mnemonics its just a jump to the end label for the current switch block.
Agree :biggrin:
... all that discussion about a feature that can implemented as macro.
BTW: the repo needs more than 100MB because of broken ignore-file (seems like a good candidate for git's "nuclear option").
Quote from: qWord on April 28, 2016, 10:10:34 AM
... all that discussion about a feature that can implemented as macro.
You are so right qWord, we could survive even without that macro :biggrin:
People could survive even without programming (I am excepted), my mum is already 87 and newer did one line of programming :bgrin:
My granny lived stunning 96 years without even knowing that programming exists, not to mention that she died without knowing who is Leonardo da Vinchi, Socrates, Aristotle or even Frank Sinatra, she only knew about Jesus Christ as much as she was told. She would probably stay alive for maybe another 50 years, but she was bored to death because she was not able to do gardening any more so she just died of boredom :(
I was wondering, if she knew about that .SWITCH feature, would she decide to stay in this world a little bit longer 8)
Hallo,
I've got a construction problem in this version of code
hook_mem64 proc uc_:ptr qword, typ_:ptr qword, adr_:ptr qword, size_:ptr qword, value_:ptr qword, user_data_:ptr qword ;
mov r10, size_
mov r11, adr_
mov rax, typ_
.switch rax
.case UC_MEM_READ
mov r8d, r9d
lea rcx, Memory_beingREAD ; ">>> Memory is being READ at 0x%llX, dat"...
mov rdx, r11
call printf_PE
;pop rdx
.break
.case UC_MEM_WRITE
mov r9, value_
lea rcx, Memory_beingWRITE ; ">>> Memory is being WRITE at 0x%llX, da"...
mov r8d, r10d
mov rdx, r11
call printf_PE
.break
.endswitch
ret
hook_mem64 endp
Error occurs here
Quote00007FF66A8B16A0
, where after the jump in
Quote00007FF66A8B16AB
,
Quote00007FF66A8B16A0 | 52 | push rdx
no return will be fulfilled, in the stack will be the extra data, and the program closes with an error, a temporary correction is made so - pop rdx written in
Quote.case UC_MEM_READ
. Compiler Options
Quote.686
.MMX
.XMM
.x64
option casemap:none
option win64:11; win64:3
option frame:auto
option stackbase:rsp
That's my fault? Or is it a build error?
00007FF66A8B1649 | 48 89 54 24 10 | mov qword ptr ss:[rsp+10],rdx |
00007FF66A8B164E | 4C 89 44 24 18 | mov qword ptr ss:[rsp+18],r8 |
00007FF66A8B1653 | 4C 89 4C 24 20 | mov qword ptr ss:[rsp+20],r9 |
00007FF66A8B1658 | 4C 8B 54 24 20 | mov r10,qword ptr ss:[rsp+20] |
00007FF66A8B165D | 4C 8B 5C 24 18 | mov r11,qword ptr ss:[rsp+18] |
00007FF66A8B1662 | 48 8B 44 24 10 | mov rax,qword ptr ss:[rsp+10] |
00007FF66A8B1667 | EB 37 | jmp win64test.7FF66A8B16A0 |
00007FF66A8B1669 | 45 8B C1 | mov r8d,r9d |
00007FF66A8B166C | 48 8D 0D 1C 1C 00 00 | lea rcx,qword ptr ds:[7FF66A8B328F] | 7FF66A8B328F:">>> Memory is being READ at 0x%llX, data size = %u\n"
00007FF66A8B1673 | 49 8B D3 | mov rdx,r11 |
00007FF66A8B1676 | E8 56 00 00 00 | call win64test.7FF66A8B16D1 |
00007FF66A8B167B | 5A | pop rdx |
00007FF66A8B167C | EB 42 | jmp win64test.7FF66A8B16C0 |
00007FF66A8B167E | EB 40 | jmp win64test.7FF66A8B16C0 |
00007FF66A8B1680 | 4C 8B 4C 24 28 | mov r9,qword ptr ss:[rsp+28] |
00007FF66A8B1685 | 48 8D 0D 37 1C 00 00 | lea rcx,qword ptr ds:[7FF66A8B32C3] | 7FF66A8B32C3:">>> Memory is being WRITE at 0x%llX, data size = %u, data value = 0x%llX\n"
00007FF66A8B168C | 45 8B C2 | mov r8d,r10d |
00007FF66A8B168F | 49 8B D3 | mov rdx,r11 |
00007FF66A8B1692 | E8 3A 00 00 00 | call win64test.7FF66A8B16D1 |
00007FF66A8B1697 | EB 27 | jmp win64test.7FF66A8B16C0 |
00007FF66A8B1699 | EB 25 | jmp win64test.7FF66A8B16C0 |
00007FF66A8B169B | 0F 1F 44 00 00 | nop dword ptr ds:[rax+rax] |
00007FF66A8B16A0 | 52 | push rdx |
00007FF66A8B16A1 | 48 C7 C2 10 00 00 00 | mov rdx,10 |
00007FF66A8B16A8 | 48 3B C2 | cmp rax,rdx |
00007FF66A8B16AB | 74 BC | je win64test.7FF66A8B1669 |
00007FF66A8B16AD | 48 C7 C2 11 00 00 00 | mov rdx,11 |
00007FF66A8B16B4 | 48 3B C2 | cmp rax,rdx |
00007FF66A8B16B7 | 5A | pop rdx |
00007FF66A8B16B8 | 74 C6 | je win64test.7FF66A8B1680 |
00007FF66A8B16BA | EB 04 | jmp win64test.7FF66A8B16C0 |
00007FF66A8B16BC | 0F 1F 40 00 | nop dword ptr ds:[rax] |
00007FF66A8B16C0 | 48 83 C4 00 | add rsp,0 |
00007FF66A8B16C4 | C3 | ret |
Regards
Hallo,
perfect timing :biggrin:, today's hjwasm update no longer causes an error :t
Regards!
Glad to hear that :biggrin:
BTW, I can see that you are using option win64:3
The safest way is to let HJWasm take care of the stack alignment and registers with: option win64:11
Quote from: habran on June 09, 2016, 11:21:14 PM
Glad to hear that :biggrin:
BTW, I can see that you are using option win64:3
The safest way is to let HJWasm take care of the stack alignment and registers with: option win64:11
Thank you! I've commented out option -win64:3 :t