It appears that OPTION LITERALS does not work properly in 32 bits.
In the code below if I remove the semicolon from "USELITERALS equ 1" the problems start. Strings are accepted in RtlInitAnsiString but produce garbage. printf does not accept the literal.
.386
;USELITERALS equ 1
.model Flat, C
option Casemap :None
IFDEF USELITERALS
OPTION LITERALS:ON ; Allow string literals use in INVOKE
ENDIF
TRUE equ 1
includelib \masm32\lib\ntdll.lib
RtlCompareString PROTO STDCALL :ptr,:ptr,:BYTE
RtlInitAnsiString PROTO STDCALL :ptr, :ptr
includelib \masm32\lib\msvcrt.lib
printf PROTO :PTR, :vararg
includelib \masm32\lib\kernel32.lib
ExitProcess proto STDCALL :dword
_STRING struct
_Length word ?
_Maximumlength word ?
_Buffer dword ?
_STRING ends
.data
format db 'result: %d',13,10,0
s1 db "someStr",0 ;
s2 db "anotherStr",0 ;
.code
main proc
LOCAL str1 : _STRING
LOCAL str2 : _STRING
IFDEF USELITERALS
INVOKE RtlInitAnsiString, addr str1, "someStr"
INVOKE RtlInitAnsiString, addr str2, "anotherStr"
INVOKE RtlCompareString, addr str1, addr str2, TRUE
INVOKE printf, "result: %d", eax
ELSE
INVOKE RtlInitAnsiString, addr str1, addr s1
INVOKE RtlInitAnsiString, addr str2, addr s2
INVOKE RtlCompareString, addr str1, addr str2, TRUE
INVOKE printf, addr format, eax
ENDIF
INVOKE ExitProcess,0
main endp
end main
But if I define the prototype of printf as "printf PROTO :PTR, :PTR" it works.
In this case the variation:
INVOKE RtlInitAnsiString, addr str1, "someStr"
INVOKE RtlInitAnsiString, addr str2, "anotherStr"
INVOKE RtlCompareString, addr str1, addr str2, TRUE
INVOKE printf, "result: %d", eax
will work.
But this will not:
INVOKE RtlInitAnsiString, addr str1, "someStr"
INVOKE RtlInitAnsiString, addr str2, "anotherStr"
INVOKE RtlCompareString, addr str1, addr str2, TRUE
INVOKE printf, addr format, eax
That is, we will be forced to use always literals on INVOKE.
So, it appears there are 2 problems:
1) Once you use literals on one parameter it expects ptr arguments on the following parameters.
2) You can not decide when to use literals or not once you subscribe the LITERALS option.
Hi aw27 :biggrin:
That is interesting find you've got there :shock:
At the moment I am busy with the SWITCH-CASE-ENDSWITCH and Johnsa is still on holidays, if he doesn't return soon I'll look at that issue as soon as I finish that new stuff that I am working on.
The fix will be included in next release together with the new stuff as soon as Johnsa returns.
No worries, fortunately the default alternative OPTION LITERALS:OFF works well :t
Hey,
(Still on holiday.. sort of) :)
The decision for string literals to only work with type PTR was intentional.. There was a lot of code where one might find something like this:
aFunction PROTO :DWORD
which was being called with
invoke aFunction, "abcd"
Technically string immediates were already supported as long as it fitted in the corresponding type, "A", "AB", "ABCD" etc.. So to avoid a) confusion and b) breaking existing code I used a combination that would
never have existed previously, no one would have a called a function with a type declared as PTR with a string/character immediate value.
As for the other issues that shouldn't happen and I will investigate if Habran doesn't beat me to it :)
Quote from: johnsa on August 13, 2017, 05:24:31 AM
The decision for string literals to only work with type PTR was intentional
The real problem is not that, I tried to explain it with the printf case. ;)
Got it :)
Just wanted to make that clear for anyone who was trying to use them with existing prototypes.
Will get onto the other issues asap :)
Hi aw27,
If you use :printf PROTO :PTR, :vararg
the INVOKE printf, "result: %d", eax will not assemble
but printf PROTO :PTR, :PTR works fine ( see example below)
That means that Johnsa prevented an purpose that to occur because vararg can contain anyting
I'll leave it to him to decide if he will change it or not.
--- strliterals.asm ------------------------------------------------------------
1: .386
2:
3: USELITERALS equ 1
4:
5: .model Flat, C
6: option Casemap :None
7: IFDEF USELITERALS
8: OPTION LITERALS:ON ; Allow string literals use in INVOKE
9: ENDIF
10:
11: TRUE equ 1
12:
13: includelib \masm32\lib\ntdll.lib
14: RtlCompareString PROTO STDCALL :ptr,:ptr,:BYTE
15: RtlInitAnsiString PROTO STDCALL :ptr, :ptr
16:
17: includelib \masm32\lib\msvcrt.lib
18: printf PROTO :PTR, :PTR
19:
20: includelib \masm32\lib\kernel32.lib
21: ExitProcess proto STDCALL :dword
22:
23: _STRING struct
24: _Length word ?
25: _Maximumlength word ?
26: _Buffer dword ?
27: _STRING ends
28:
29: .data
30: format db 'result: %d',13,10,0
31: s1 db "someStr",0 ;
32: s2 db "anotherStr",0 ;
33:
34: .code
35:
36: main proc
009B1010 55 push ebp
009B1011 8B EC mov ebp,esp
009B1013 83 EC 10 sub esp,10h
37: LOCAL str1 : _STRING
38: LOCAL str2 : _STRING
39: INVOKE RtlInitAnsiString, addr str1, "someStr"
009B1016 68 49 50 9B 00 push 9B5049h
009B101B 8D 45 F8 lea eax,[str1]
009B101E 50 push eax
009B101F E8 90 00 00 00 call _RtlInitAnsiString@8 (09B10B4h)
40: INVOKE RtlInitAnsiString, addr str2, "anotherStr"
009B1024 68 51 50 9B 00 push 9B5051h
009B1029 8D 45 F0 lea eax,[str2]
009B102C 50 push eax
009B102D E8 82 00 00 00 call _RtlInitAnsiString@8 (09B10B4h)
41: INVOKE RtlCompareString, addr str1, addr str2, TRUE
009B1032 6A 01 push 1
009B1034 8D 45 F0 lea eax,[str2]
009B1037 50 push eax
009B1038 8D 45 F8 lea eax,[str1]
009B103B 50 push eax
009B103C E8 6D 00 00 00 call _RtlCompareString@12 (09B10AEh)
42: INVOKE printf, "result: %d", eax
009B1041 50 push eax
42: INVOKE printf, "result: %d", eax
009B1042 68 3E 50 9B 00 push 9B503Eh
009B1047 E8 6E 00 00 00 call _printf (09B10BAh)
009B104C 83 C4 08 add esp,8
43:
44: INVOKE RtlInitAnsiString, addr str1, "someStr"
009B104F 68 49 50 9B 00 push 9B5049h
009B1054 8D 45 F8 lea eax,[str1]
009B1057 50 push eax
009B1058 E8 57 00 00 00 call _RtlInitAnsiString@8 (09B10B4h)
45: INVOKE RtlInitAnsiString, addr str2, "anotherStr"
009B105D 68 51 50 9B 00 push 9B5051h
009B1062 8D 45 F0 lea eax,[str2]
009B1065 50 push eax
009B1066 E8 49 00 00 00 call _RtlInitAnsiString@8 (09B10B4h)
46: INVOKE RtlCompareString, addr str1, addr str2, TRUE
009B106B 6A 01 push 1
009B106D 8D 45 F0 lea eax,[str2]
009B1070 50 push eax
009B1071 8D 45 F8 lea eax,[str1]
009B1074 50 push eax
009B1075 E8 34 00 00 00 call _RtlCompareString@12 (09B10AEh)
47: INVOKE printf, addr format, eax
009B107A 50 push eax
009B107B 68 00 50 9B 00 push 9B5000h
009B1080 E8 35 00 00 00 call _printf (09B10BAh)
009B1085 83 C4 08 add esp,8
48:
49: INVOKE ExitProcess,0
009B1088 6A 00 push 0
009B108A E8 35 10 00 00 call _ExitProcess@4 (09B20C4h)
--- No source file -------------------------------------------------------------
Here is a simple solution without changing UASM code: 8)
Quote
IFDEF USELITERALS
OPTION LITERALS:ON ; Allow string literals use in INVOKE
printf PROTO :PTR, :PTR
ELSE
printf PROTO :PTR, :vararg
ENDIF
--- strliterals.asm ------------------------------------------------------------
1: .386
2:
3: USELITERALS equ 1
4:
5: .model Flat, C
6: option Casemap :None
7: IFDEF USELITERALS
8: OPTION LITERALS:ON ; Allow string literals use in INVOKE
9: printf PROTO :PTR, :PTR
10: ELSE
11: printf PROTO :PTR, :vararg
12: ENDIF
13:
14: TRUE equ 1
15:
16: includelib \masm32\lib\ntdll.lib
17: RtlCompareString PROTO STDCALL :ptr,:ptr,:BYTE
18: RtlInitAnsiString PROTO STDCALL :ptr, :ptr
19:
20: includelib \masm32\lib\msvcrt.lib
21:
22: includelib \masm32\lib\kernel32.lib
23: ExitProcess proto STDCALL :dword
24:
25: _STRING struct
26: _Length word ?
27: _Maximumlength word ?
28: _Buffer dword ?
29: _STRING ends
30:
31: .data
32: format db 'result: %d',13,10,0
33: s1 db "someStr",0 ;
34: s2 db "anotherStr",0 ;
35:
36: .code
37:
38: main proc
01291010 55 push ebp
01291011 8B EC mov ebp,esp
01291013 83 EC 10 sub esp,10h
39: LOCAL str1 : _STRING
40: LOCAL str2 : _STRING
41: IFDEF USELITERALS
42: INVOKE RtlInitAnsiString, addr str1, "someStr"
01291016 68 20 50 29 01 push 1295020h
0129101B 8D 45 F8 lea eax,[str1]
0129101E 50 push eax
0129101F E8 90 00 00 00 call _RtlInitAnsiString@8 (012910B4h)
43: INVOKE RtlInitAnsiString, addr str2, "anotherStr"
01291024 68 28 50 29 01 push 1295028h
01291029 8D 45 F0 lea eax,[str2]
0129102C 50 push eax
0129102D E8 82 00 00 00 call _RtlInitAnsiString@8 (012910B4h)
44: INVOKE RtlCompareString, addr str1, addr str2, TRUE
01291032 6A 01 push 1
01291034 8D 45 F0 lea eax,[str2]
01291037 50 push eax
01291038 8D 45 F8 lea eax,[str1]
0129103B 50 push eax
0129103C E8 6D 00 00 00 call _RtlCompareString@12 (012910AEh)
45: INVOKE printf, "result: %d", eax
01291041 50 push eax
01291042 68 3E 50 29 01 push 129503Eh
01291047 E8 6E 00 00 00 call _printf (012910BAh)
0129104C 83 C4 08 add esp,8
46: ELSE
47: INVOKE RtlInitAnsiString, addr str1, addr s1
48: INVOKE RtlInitAnsiString, addr str2, addr s2
49: INVOKE RtlCompareString, addr str1, addr str2, TRUE
50: INVOKE printf, addr format, eax
51: ENDIF
52:
53: INVOKE ExitProcess,0
0129104F 6A 00 push 0
01291051 E8 6E 10 00 00 call _ExitProcess@4 (012920C4h)
--- No source file -------------------------------------------------------------
Thank you for the hints and heads up, habran :t
:biggrin:
New, exciting UASM2.39 is coming soon, with SWITCH-CASE-ENDSWITCH with all data stored in _DATA section
so that debugging makes easy, here is an example:
mov eax,1003
.switch eax
.case 300
mov edx,300
.case 1001
mov edx,1
.case 1002
mov edx,2
.case 1003
mov edx,3
.case 1004
mov edx,5
.case 1005
mov edx,6
.case 1006
mov edx,7
.case 1009
.case 1040
mov edx,1
.case 1041
mov edx,1
.case 1042
mov edx,2
.case 1043
mov edx,3
.case 1044
mov edx,5
.case 1045
mov edx,6
.case 1046
mov edx,7
.case 1049
.case 1099
mov edx,1
.case 1031
mov edx,1
.case 902
mov edx,2
.case 1083
mov edx,3
.case 1084
mov edx,5
.case 1085
mov edx,6
.case 1086
mov edx,7
.case 1089
.case 1090
mov edx,1
.case 1121
mov edx,1
.case 1092
mov edx,2
.case 1093
mov edx,3
.case 1094
mov edx,5
.case 1095
mov edx,6
.case 1056
mov edx,7
.case 1059
.case 1011
mov edx,1
.case 1052
mov edx,2
.case 1053
mov edx,3
.case 1054
mov edx,5
.case 1055
mov edx,6
.case 1066
mov edx,7
.case 1069
.case 1070
mov edx,1
.case 1071
mov edx,1
.case 1102
mov edx,2
.case 1103
mov edx,3
.case 1104
mov edx,5
.case 1105
mov edx,6
.case 1106
mov edx,7
.case 1109
mov edx,1109
.case 1100
mov edx,1
.case 1061
mov edx,1
.case 1012
mov edx,2
.case 1013
mov edx,3
.case 1014
mov edx,5
.case 1015
mov edx,6
.case 1016
mov edx,7
.case 1019
mov edx,8
.default
mov edx,9
.endswitch
Debug:
146: mov eax,1003
011D11D6 B8 EB 03 00 00 mov eax,3EBh
147: .switch eax
011D11DB E9 F4 01 00 00 jmp WndProc+204h (011D13D4h)
148: .case 300
149: mov edx,300
011D11E0 BA 2C 01 00 00 mov edx,12Ch
150: .case 1001
011D11E5 E9 17 02 00 00 jmp WndProc+231h (011D1401h)
151: mov edx,1
011D11EA BA 01 00 00 00 mov edx,1
152: .case 1002
011D11EF E9 0D 02 00 00 jmp WndProc+231h (011D1401h)
153: mov edx,2
011D11F4 BA 02 00 00 00 mov edx,2
154: .case 1003
011D11F9 E9 03 02 00 00 jmp WndProc+231h (011D1401h)
155: mov edx,3
011D11FE BA 03 00 00 00 mov edx,3
156: .case 1004
011D1203 E9 F9 01 00 00 jmp WndProc+231h (011D1401h)
157: mov edx,5
011D1208 BA 05 00 00 00 mov edx,5
158: .case 1005
011D120D E9 EF 01 00 00 jmp WndProc+231h (011D1401h)
159: mov edx,6
011D1212 BA 06 00 00 00 mov edx,6
160: .case 1006
011D1217 E9 E5 01 00 00 jmp WndProc+231h (011D1401h)
161: mov edx,7
011D121C BA 07 00 00 00 mov edx,7
162: .case 1009
011D1221 E9 DB 01 00 00 jmp WndProc+231h (011D1401h)
163: .case 1040
011D1226 E9 D6 01 00 00 jmp WndProc+231h (011D1401h)
164: mov edx,1
011D122B BA 01 00 00 00 mov edx,1
165: .case 1041
011D1230 E9 CC 01 00 00 jmp WndProc+231h (011D1401h)
166: mov edx,1
011D1235 BA 01 00 00 00 mov edx,1
167: .case 1042
011D123A E9 C2 01 00 00 jmp WndProc+231h (011D1401h)
168: mov edx,2
011D123F BA 02 00 00 00 mov edx,2
169: .case 1043
011D1244 E9 B8 01 00 00 jmp WndProc+231h (011D1401h)
170: mov edx,3
011D1249 BA 03 00 00 00 mov edx,3
171: .case 1044
011D124E E9 AE 01 00 00 jmp WndProc+231h (011D1401h)
172: mov edx,5
011D1253 BA 05 00 00 00 mov edx,5
173: .case 1045
011D1258 E9 A4 01 00 00 jmp WndProc+231h (011D1401h)
174: mov edx,6
011D125D BA 06 00 00 00 mov edx,6
175: .case 1046
011D1262 E9 9A 01 00 00 jmp WndProc+231h (011D1401h)
176: mov edx,7
011D1267 BA 07 00 00 00 mov edx,7
177: .case 1049
011D126C E9 90 01 00 00 jmp WndProc+231h (011D1401h)
178: .case 1099
011D1271 E9 8B 01 00 00 jmp WndProc+231h (011D1401h)
179: mov edx,1
011D1276 BA 01 00 00 00 mov edx,1
180: .case 1031
011D127B E9 81 01 00 00 jmp WndProc+231h (011D1401h)
181: mov edx,1
011D1280 BA 01 00 00 00 mov edx,1
182: .case 902
011D1285 E9 77 01 00 00 jmp WndProc+231h (011D1401h)
183: mov edx,2
011D128A BA 02 00 00 00 mov edx,2
184: .case 1083
011D128F E9 6D 01 00 00 jmp WndProc+231h (011D1401h)
185: mov edx,3
011D1294 BA 03 00 00 00 mov edx,3
186: .case 1084
011D1299 E9 63 01 00 00 jmp WndProc+231h (011D1401h)
187: mov edx,5
011D129E BA 05 00 00 00 mov edx,5
188: .case 1085
011D12A3 E9 59 01 00 00 jmp WndProc+231h (011D1401h)
189: mov edx,6
011D12A8 BA 06 00 00 00 mov edx,6
190: .case 1086
011D12AD E9 4F 01 00 00 jmp WndProc+231h (011D1401h)
191: mov edx,7
011D12B2 BA 07 00 00 00 mov edx,7
192: .case 1089
011D12B7 E9 45 01 00 00 jmp WndProc+231h (011D1401h)
193: .case 1090
011D12BC E9 40 01 00 00 jmp WndProc+231h (011D1401h)
194: mov edx,1
011D12C1 BA 01 00 00 00 mov edx,1
195: .case 1121
011D12C6 E9 36 01 00 00 jmp WndProc+231h (011D1401h)
196: mov edx,1
011D12CB BA 01 00 00 00 mov edx,1
197: .case 1092
011D12D0 E9 2C 01 00 00 jmp WndProc+231h (011D1401h)
198: mov edx,2
011D12D5 BA 02 00 00 00 mov edx,2
199: .case 1093
011D12DA E9 22 01 00 00 jmp WndProc+231h (011D1401h)
200: mov edx,3
011D12DF BA 03 00 00 00 mov edx,3
201: .case 1094
011D12E4 E9 18 01 00 00 jmp WndProc+231h (011D1401h)
202: mov edx,5
011D12E9 BA 05 00 00 00 mov edx,5
203: .case 1095
011D12EE E9 0E 01 00 00 jmp WndProc+231h (011D1401h)
204: mov edx,6
011D12F3 BA 06 00 00 00 mov edx,6
205: .case 1056
011D12F8 E9 04 01 00 00 jmp WndProc+231h (011D1401h)
206: mov edx,7
011D12FD BA 07 00 00 00 mov edx,7
207: .case 1059
011D1302 E9 FA 00 00 00 jmp WndProc+231h (011D1401h)
208: .case 1011
011D1307 E9 F5 00 00 00 jmp WndProc+231h (011D1401h)
209: mov edx,1
011D130C BA 01 00 00 00 mov edx,1
210: .case 1052
011D1311 E9 EB 00 00 00 jmp WndProc+231h (011D1401h)
211: mov edx,2
011D1316 BA 02 00 00 00 mov edx,2
212: .case 1053
011D131B E9 E1 00 00 00 jmp WndProc+231h (011D1401h)
213: mov edx,3
011D1320 BA 03 00 00 00 mov edx,3
214: .case 1054
011D1325 E9 D7 00 00 00 jmp WndProc+231h (011D1401h)
215: mov edx,5
011D132A BA 05 00 00 00 mov edx,5
216: .case 1055
011D132F E9 CD 00 00 00 jmp WndProc+231h (011D1401h)
217: mov edx,6
011D1334 BA 06 00 00 00 mov edx,6
218: .case 1066
011D1339 E9 C3 00 00 00 jmp WndProc+231h (011D1401h)
219: mov edx,7
011D133E BA 07 00 00 00 mov edx,7
220: .case 1069
011D1343 E9 B9 00 00 00 jmp WndProc+231h (011D1401h)
221: .case 1070
011D1348 E9 B4 00 00 00 jmp WndProc+231h (011D1401h)
222: mov edx,1
011D134D BA 01 00 00 00 mov edx,1
223: .case 1071
011D1352 E9 AA 00 00 00 jmp WndProc+231h (011D1401h)
224: mov edx,1
011D1357 BA 01 00 00 00 mov edx,1
225: .case 1102
011D135C E9 A0 00 00 00 jmp WndProc+231h (011D1401h)
226: mov edx,2
011D1361 BA 02 00 00 00 mov edx,2
227: .case 1103
011D1366 E9 96 00 00 00 jmp WndProc+231h (011D1401h)
228: mov edx,3
011D136B BA 03 00 00 00 mov edx,3
229: .case 1104
011D1370 E9 8C 00 00 00 jmp WndProc+231h (011D1401h)
230: mov edx,5
011D1375 BA 05 00 00 00 mov edx,5
231: .case 1105
011D137A E9 82 00 00 00 jmp WndProc+231h (011D1401h)
232: mov edx,6
011D137F BA 06 00 00 00 mov edx,6
233: .case 1106
011D1384 EB 7B jmp WndProc+231h (011D1401h)
234: mov edx,7
011D1386 BA 07 00 00 00 mov edx,7
235: .case 1109
011D138B EB 74 jmp WndProc+231h (011D1401h)
236: mov edx,1109
011D138D BA 55 04 00 00 mov edx,455h
237: .case 1100
011D1392 EB 6D jmp WndProc+231h (011D1401h)
238: mov edx,1
011D1394 BA 01 00 00 00 mov edx,1
239: .case 1061
011D1399 EB 66 jmp WndProc+231h (011D1401h)
240: mov edx,1
011D139B BA 01 00 00 00 mov edx,1
241: .case 1012
011D13A0 EB 5F jmp WndProc+231h (011D1401h)
242: mov edx,2
011D13A2 BA 02 00 00 00 mov edx,2
243: .case 1013
011D13A7 EB 58 jmp WndProc+231h (011D1401h)
244: mov edx,3
011D13A9 BA 03 00 00 00 mov edx,3
245: .case 1014
011D13AE EB 51 jmp WndProc+231h (011D1401h)
246: mov edx,5
011D13B0 BA 05 00 00 00 mov edx,5
247: .case 1015
011D13B5 EB 4A jmp WndProc+231h (011D1401h)
248: mov edx,6
011D13B7 BA 06 00 00 00 mov edx,6
249: .case 1016
011D13BC EB 43 jmp WndProc+231h (011D1401h)
250: mov edx,7
011D13BE BA 07 00 00 00 mov edx,7
251: .case 1019
011D13C3 EB 3C jmp WndProc+231h (011D1401h)
252: mov edx,8
011D13C5 BA 08 00 00 00 mov edx,8
253: .default
011D13CA EB 35 jmp WndProc+231h (011D1401h)
254: mov edx,9
011D13CC BA 09 00 00 00 mov edx,9
255: .endswitch
011D13D1 EB 2E jmp WndProc+231h (011D1401h)
011D13D3 90 nop
011D13D4 3D 2C 01 00 00 cmp eax,12Ch
011D13D9 7C F1 jl WndProc+1FCh (011D13CCh)
011D13DB 3D 61 04 00 00 cmp eax,461h
011D13E0 77 EA ja WndProc+1FCh (011D13CCh)
011D13E2 50 push eax
011D13E3 52 push edx
011D13E4 8D 15 18 51 1D 01 lea edx,ds:[11D5118h]
011D13EA 2D 2C 01 00 00 sub eax,12Ch
011D13EF 0F B7 14 42 movzx edx,word ptr [edx+eax*2]
011D13F3 8D 05 3A 50 1D 01 lea eax,ds:[11D503Ah]
011D13F9 8B 04 90 mov eax,dword ptr [eax+edx*4]
011D13FC 5A pop edx
011D13FD 87 04 24 xchg eax,dword ptr [esp]
011D1400 C3 ret
256:
The actual mechanic to calculate the jump is this:
255: .endswitch
011D13D1 EB 2E jmp WndProc+231h (011D1401h)
011D13D3 90 nop
011D13D4 3D 2C 01 00 00 cmp eax,12Ch
011D13D9 7C F1 jl WndProc+1FCh (011D13CCh)
011D13DB 3D 61 04 00 00 cmp eax,461h
011D13E0 77 EA ja WndProc+1FCh (011D13CCh)
011D13E2 50 push eax
011D13E3 52 push edx
011D13E4 8D 15 18 51 1D 01 lea edx,ds:[11D5118h]
011D13EA 2D 2C 01 00 00 sub eax,12Ch
011D13EF 0F B7 14 42 movzx edx,word ptr [edx+eax*2]
011D13F3 8D 05 3A 50 1D 01 lea eax,ds:[11D503Ah]
011D13F9 8B 04 90 mov eax,dword ptr [eax+edx*4]
011D13FC 5A pop edx
011D13FD 87 04 24 xchg eax,dword ptr [esp]
011D1400 C3 ret
256:
I have on purpose used a big gap between the lowest and highest case to show that there is no data in the _CODE section
here is the listing which shows actual data used to calculate the jump:
00000000 * .data
00000354 * _TEXT ends
0000003A * _DATA segment
* assume cs:ERROR
0000003A 000000000000000000* @C0006 dd @C000B, @C001D, @C000C, @C000D, @C000E, @C000F, @C0010, @C0011, @C0012, @C002B, @C003C, @C003D, @C003E, @C003F, @C0040, @C0041, @C001C, @C0013, @C0014, @C0015
0000008A 000000000000000000* dd @C0016, @C0017, @C0018, @C0019, @C001A, @C002C, @C002D, @C002E, @C002F, @C0029, @C002A, @C003B, @C0030, @C0031, @C0032, @C0033, @C001E, @C001F, @C0020, @C0021
000000DA 000000000000000000* dd @C0022, @C0023, @C0025, @C0026, @C0027, @C0028, @C001B, @C003A, @C0034, @C0035, @C0036, @C0037, @C0038, @C0039, @C0024
00000116 0000 * ALIGN 4
00000118 000037003700370037* @C0008 dw 0,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
0000017C 370037003700370037* dw 55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
000001E0 370037003700370037* dw 55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
00000244 370037003700370037* dw 55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
000002A8 370037003700370037* dw 55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
0000030C 370037003700370037* dw 55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
00000370 370037003700370037* dw 55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
000003D4 370037003700370037* dw 55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
00000438 370037003700370037* dw 55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
0000049C 370037003700370037* dw 55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
00000500 370037003700370037* dw 55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
00000564 370037003700370037* dw 55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
000005C8 370037000100370037* dw 55,55,1,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
0000062C 370037003700370037* dw 55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55
00000690 370002000300040005* dw 55,2,3,4,5,6,7,55,55,8,55,9,10,11,12,13,14,55,55,15,55,55,55,55,55,55,55,55,55,55,55,16,55,55,55,55,55,55,55,55,17,18,19,20,21,22,23,55,55,24
000006F4 3700370019001A001B* dw 55,55,25,26,27,28,29,55,55,30,55,31,55,55,55,55,32,55,55,33,34,35,55,55,55,55,55,55,55,55,55,55,55,36,37,38,39,55,55,40,41,55,42,43,44,45,55,55,55,46
00000758 2F0037003000310032* dw 47,55,48,49,50,51,52,55,55,53,55,55,55,55,55,55,55,55,55,55,55,54
00000000 * .code
00000784 * _DATA ends
This is now not any more Ferrari but Tesla Model S P100D ;)
Quote from: habran on August 15, 2017, 08:38:23 PM
This is now not any more Ferrari but Tesla Model S P100D ;)
Thank you for the clarification. :exclaim:
It was my pleasure :biggrin:
I was always disappointed with the garbage which that HLL creates in the code section, even MSV$ does the same, now UASM jumped far, far ahead, as AUDI says:"vorsprung durch technik" :t
The advantage of that is not only clear debug code but we can put more data there to make it faster and it will not bloat the code section.
I have increased span between lowest and highest case from 512 to 2048 and it can be all executed with a few instructions from the above post.
So, if you need a speed for big amount of cases it can span from 0 to 2048
UASM has a smart logic to use different kind of solution for different types of cases to keep data as small as possible without affecting the speed, however, smart programmer will chose wisely what cases to put together to create optimal code.
In my opinion every programmer is smart, stupid can not be programmer, they can only think that they are ;)
Johnsa is still on holidays so I decided to post a new UASM here for testing SWITCH hll
here is a 64 bit
here is the32 bit version
remember, you don't need a .break because default option is SWITCHSTYLE:ASMSTYLE
so you can use:
option SWITCHSTYLE:ASMSTYLE ;this is a default
or
option SWITCHSTYLE:CSTYLE ;this will not work without the .break
examples in previous posts are the ASMSTYLE
Hi aw27,
I have found out what was wrong in your first code, it was IFDEF, if you use IF instead it works
depending on USELITERALS equ 0 or USELITERALS equ 1 it will run desired code:
.386
.model Flat, C
USELITERALS equ 0
IF USELITERALS
OPTION LITERALS:ON ; Allow string literals use in INVOKE
printf PROTO :PTR, :PTR
ELSE
printf PROTO :PTR, :vararg
ENDIF
TRUE equ 1
includelib \masm32\lib\ntdll.lib
RtlCompareString PROTO STDCALL :ptr,:ptr,:BYTE
RtlInitAnsiString PROTO STDCALL :ptr, :ptr
includelib \masm32\lib\msvcrt.lib
includelib \masm32\lib\kernel32.lib
ExitProcess proto STDCALL :dword
_STRING struct
_Length word ?
_Maximumlength word ?
_Buffer dword ?
_STRING ends
.data
format db 'result: %d',13,10,0
s1 db "someStr",0 ;
s2 db "anotherStr",0 ;
.code
main proc
LOCAL str1 : _STRING
LOCAL str2 : _STRING
IF USELITERALS
INVOKE RtlInitAnsiString, addr str1, "someStr"
INVOKE RtlInitAnsiString, addr str2, "anotherStr"
INVOKE RtlCompareString, addr str1, addr str2, TRUE
INVOKE printf, "result: %d", eax
ELSE
INVOKE RtlInitAnsiString, addr str1, addr s1
INVOKE RtlInitAnsiString, addr str2, addr s2
INVOKE RtlCompareString, addr str1, addr str2, TRUE
INVOKE printf, addr format, eax
ENDIF
INVOKE ExitProcess,0
main endp
end main
Yes, this one has bitten me occasionally (and Masm32 has several equates of this sort):
someswitch equ 0
IFDEF someswitch
echo someswitch is defined
else
echo you will NEVER reach this line
endif
better:
someswitch=0
IF someswitch
echo someswitch is ON
else
echo someswitch is OFF
endif
Thanks JJ :t
I have found it out half logically half accidentally, however, that was a good lesson for the future 8)
It would be a painstaking job to rework the current well working code to separate PTR from CONSTANT in one function parameters. I don't say it is impossible but the question is: is it worth the effort given to make it work that way? ::)
Anyway, if Johnsa doesn't share my opinion, he can "Go ahead, make my day" :lol:
Actually what I said was:
"In the code below if I remove the semicolon from "USELITERALS equ 1" the problems start"
So, if it is not there it is not defined. It it is there, even if I put USELITERALS equ 0, it is defined.
That is what we were talking about because IFDEF is not doing proper job in this case but IF
Quote from: habran on August 19, 2017, 11:02:43 PM
That is what we were talking about because IFDEF is not doing proper job in this case but IF
If you are using "IF" does it work if you put
USELITERALS equ 1
I think not, it appears that it will be equivalent to the IFDEF I used. Or is it escaping me something ?
It works, why don't you try my last source from the post #17
just change USELITERALS equ 0 to USELITERALS equ 1
The secret is to use IF instead of IFDEF
IFDEF works with system variables like IFDEF _MAC but not with constants, actually it doesn't care if it is 1 or 0, as long as it is defined it uses it as DEFINED while IF checks if it is TRUE or FALSE
This is from MSDN:
IFDEF
Grants assembly if name is a previously defined label, variable, or symbol.
IF
Grants assembly of if statements if expression1 is true (nonzero) or elseif statements if expression1 is false (0) and expression2 is true.
It gave me the idea to implement DEFINE and UNDEF in UASM for conditional assembly :idea:
It would give UASM more flexibility.
Quote from: habran on August 20, 2017, 05:44:12 AMIt gave me the idea to implement DEFINE and UNDEF in UASM for conditional assembly :idea:
It would give UASM more flexibility.
Don't make it a default option, though. While there are many people who dislike MASM for its bugs and its slowness, there are also many who simply wouldn't touch code that is only half compatible. Userbase is important, and it takes a very long time to accept that UAsm is a perfect clone...
Besides, the MySwitch=0 solution works perfectly, there is no need to change anything.
It was easier than I thought :t
It will be implemented in macrolib.c
Have look at this example, with these two macros DEFINE and UNDEF both version can be assembled at ones.
Here is the source:
.386
.model Flat, C
DEFINE MACRO a:req
a = 1
ENDM
UNDEF MACRO a:req
a = 0
ENDM
DEFINE USELITERALS
IF USELITERALS
OPTION LITERALS:ON ; Allow string literals use in INVOKE
printf PROTO :PTR, :PTR
ELSE
printf PROTO :PTR, :vararg
ENDIF
TRUE equ 1
includelib \masm32\lib\ntdll.lib
RtlCompareString PROTO STDCALL :ptr,:ptr,:BYTE
RtlInitAnsiString PROTO STDCALL :ptr, :ptr
includelib \masm32\lib\msvcrt.lib
includelib \masm32\lib\kernel32.lib
ExitProcess proto STDCALL :dword
_STRING struct
_Length word ?
_Maximumlength word ?
_Buffer dword ?
_STRING ends
.data
format db 'result: %d',13,10,0
s1 db "someStr",0 ;
s2 db "anotherStr",0 ;
.code
main proc
LOCAL str1 : _STRING
LOCAL str2 : _STRING
IF USELITERALS
INVOKE RtlInitAnsiString, addr str1, "someStr"
INVOKE RtlInitAnsiString, addr str2, "anotherStr"
INVOKE RtlCompareString, addr str1, addr str2, TRUE
INVOKE printf, "result: %d", eax
ENDIF
UNDEF USELITERALS
IF USELITERALS EQ 0
INVOKE RtlInitAnsiString, addr str1, addr s1
INVOKE RtlInitAnsiString, addr str2, addr s2
INVOKE RtlCompareString, addr str1, addr str2, TRUE
INVOKE printf, addr format, eax
ENDIF
INVOKE ExitProcess,0
main endp
end main
and here is disassembly:
1: .386
2: .model Flat, C
3:
4: DEFINE MACRO a:req
5: a = 1
6: ENDM
7:
8: UNDEF MACRO a:req
9: a = 0
10: ENDM
11:
12:
13: DEFINE USELITERALS
14: IF USELITERALS
15: OPTION LITERALS:ON ; Allow string literals use in INVOKE
16: printf PROTO :PTR, :PTR
17: ELSE
18: printf PROTO :PTR, :vararg
19: ENDIF
20:
21:
22: TRUE equ 1
23:
24: includelib \masm32\lib\ntdll.lib
25: RtlCompareString PROTO STDCALL :ptr,:ptr,:BYTE
26: RtlInitAnsiString PROTO STDCALL :ptr, :ptr
27:
28: includelib \masm32\lib\msvcrt.lib
29:
30: includelib \masm32\lib\kernel32.lib
31: ExitProcess proto STDCALL :dword
32:
33: _STRING struct
34: _Length word ?
35: _Maximumlength word ?
36: _Buffer dword ?
37: _STRING ends
38:
39: .data
40: format db 'result: %d',13,10,0
41: s1 db "someStr",0 ;
42: s2 db "anotherStr",0 ;
43:
44: .code
45:
46: main proc
009E107C 55 push ebp
009E107D 8B EC mov ebp,esp
009E107F 83 EC 10 sub esp,10h
47: LOCAL str1 : _STRING
48: LOCAL str2 : _STRING
49:
50: IF USELITERALS
51: INVOKE RtlInitAnsiString, addr str1, "someStr"
009E1082 68 20 50 9E 00 push 9E5020h
009E1087 8D 45 F8 lea eax,[str1]
009E108A 50 push eax
009E108B E8 DE FF FF FF call _RtlInitAnsiString@8 (09E106Eh)
52: INVOKE RtlInitAnsiString, addr str2, "anotherStr"
009E1090 68 28 50 9E 00 push 9E5028h
009E1095 8D 45 F0 lea eax,[str2]
009E1098 50 push eax
009E1099 E8 D0 FF FF FF call _RtlInitAnsiString@8 (09E106Eh)
53: INVOKE RtlCompareString, addr str1, addr str2, TRUE
009E109E 6A 01 push 1
009E10A0 8D 45 F0 lea eax,[str2]
009E10A3 50 push eax
009E10A4 8D 45 F8 lea eax,[str1]
009E10A7 50 push eax
009E10A8 E8 BB FF FF FF call _RtlCompareString@12 (09E1068h)
54: INVOKE printf, "result: %d", eax
009E10AD 50 push eax
009E10AE 68 3E 50 9E 00 push 9E503Eh
009E10B3 E8 BC FF FF FF call _printf (09E1074h)
009E10B8 83 C4 08 add esp,8
55: ENDIF
56: UNDEF USELITERALS
57: IF USELITERALS EQ 0
58: INVOKE RtlInitAnsiString, addr str1, addr s1
009E10BB 68 0D 50 9E 00 push 9E500Dh
009E10C0 8D 45 F8 lea eax,[str1]
009E10C3 50 push eax
009E10C4 E8 A5 FF FF FF call _RtlInitAnsiString@8 (09E106Eh)
59: INVOKE RtlInitAnsiString, addr str2, addr s2
009E10C9 68 15 50 9E 00 push 9E5015h
009E10CE 8D 45 F0 lea eax,[str2]
009E10D1 50 push eax
009E10D2 E8 97 FF FF FF call _RtlInitAnsiString@8 (09E106Eh)
60: INVOKE RtlCompareString, addr str1, addr str2, TRUE
009E10D7 6A 01 push 1
60: INVOKE RtlCompareString, addr str1, addr str2, TRUE
009E10D9 8D 45 F0 lea eax,[str2]
009E10DC 50 push eax
009E10DD 8D 45 F8 lea eax,[str1]
009E10E0 50 push eax
009E10E1 E8 82 FF FF FF call _RtlCompareString@12 (09E1068h)
61: INVOKE printf, addr format, eax
009E10E6 50 push eax
009E10E7 68 00 50 9E 00 push 9E5000h
009E10EC E8 83 FF FF FF call _printf (09E1074h)
009E10F1 83 C4 08 add esp,8
62: ENDIF
63:
64: INVOKE ExitProcess,0
009E10F4 6A 00 push 0
009E10F6 E8 83 0F 00 00 call _ExitProcess@4 (09E207Eh)
JJ2007 :biggrin:
as you can see, these two macros will be implemented in next releases as macros in macrolib.c, however, if you insist to use some other assembler you can just use these macros direct in your source free of charges ;)
Our goal with UASM is not to create a clone of ml.exe or ml64.exe that would be such a waste of time and effort.
UASM is a modern assembler which is still able to assemble old sources from masm32 and newest from ml64, but also far far more advanced and capable.
We dislike tradition, conservatism and all kind of similar bullism :biggrin:
Quote from: habran on August 20, 2017, 05:44:12 AM
It works, why don't you try my last source from the post #17
just change USELITERALS equ 0 to USELITERALS equ 1
The secret is to use IF instead of IFDEF
That is not the secret, the secret is that you changed the prototype of printf to make it work. :icon_eek:
Actually, I was the first to mention that it would work if we change the prototype of printf. Of course, I was not saying that changing prototypes of functions to make uasm work was a solution, I was trying to provide leads to help fix the problem.
After due consideration I will change vararg to allow string literals. I cannot see any reason for concern with doing so, it's very unlikely that someone would need or want to pass something like "abcd" to a vararg and expect it to be the numerical value, a string literal is far more likely and useful with option literals:on
That said Habran's additions with regards to define/undef are quite useful too so we'll keep both for more flexibility.
deleted
Good thinking, Nidud :biggrin:
I can see that PURGE directive can be quite useful, however, I am not familiar with PURGE directive, I never used it. Can you give me one example of its usage.
I am sure that DEFINE can be implemented in C source to be more useful. I did it with macro to see if it can find a purpose in ASM programming. If so, we can than extend its usage. I'd like to have it built in as assembly directive.
deleted
I have implemented it and works well. :t
The advantage is that it reports an error if the variable is not defined, while macro doesn't :eusa_clap:
DEFINE macro is fine in that regard and it can stay as macro.
Hey,
Right so we've put in some other changes to 2.39 and fixes apart from the really cool DEFINE/UNDEF directives which now means BOTH of these styles work simultaneously with option literals:on
.386
.model Flat, C
option Casemap :None
OPTION LITERALS:ON ; Allow string literals use in INVOKE
TRUE equ 1
includelib c:\masm32\lib\ntdll.lib
RtlCompareString PROTO STDCALL :ptr,:ptr,:BYTE
RtlInitAnsiString PROTO STDCALL :ptr, :ptr
includelib c:\masm32\lib\msvcrt.lib
printf PROTO :PTR, :vararg
includelib c:\masm32\lib\kernel32.lib
ExitProcess proto STDCALL :dword
_STRING struct
_Length word ?
_Maximumlength word ?
_Buffer dword ?
_STRING ends
.data
format db "result: %d",13,10,"%s",13,10,0
s1 db "someStr",0 ;
s2 db "anotherStr",0 ;
.code
main proc
LOCAL str1 : _STRING
LOCAL str2 : _STRING
INVOKE RtlInitAnsiString, addr str1, "someStr"
INVOKE RtlInitAnsiString, addr str2, "anotherStr"
INVOKE RtlCompareString, addr str1, addr str2, TRUE
INVOKE printf, "result: %d\n%s\n", eax, "test"
INVOKE RtlInitAnsiString, addr str1, addr s1
INVOKE RtlInitAnsiString, addr str2, addr s2
INVOKE RtlCompareString, addr str1, addr str2, TRUE
INVOKE printf, addr format, eax, addr s1
INVOKE ExitProcess,0
main endp
end main
Good modification John. :t
include \masm32\include\masm32rt.inc
OPTION LITERALS:ON
.code
start:
invoke WriteConsole, rv(GetStdHandle, STD_OUTPUT_HANDLE), "this is a string", 16, 0, 0
invoke WriteConsole, rv(GetStdHandle, STD_OUTPUT_HANDLE), cfm$("this\nis a\nstring\n"), 20, 0, 0
inkey "ok?"
exit
end start
The first WriteConsole line chokes withError A2145: INVOKE argument type mismatch: argument 2
Tmp_File.asm(8) : Error A2274: Constant value too large: 74686973206973206120737472696E67h
Which syntax would work correctly?
The second line works fine with version 2.39, not surprisingly - after all, cfm$() is a well-tested Masm32 macro. Besides, it remains compatible with MASM, in contrast to the first line.
However, with version 2.38 of 2 August, it producessiht
a si
gnirts
?ko
;)
@JJ,
The team has said that it is necessary the argument to be a pointer to use a literal.
The prototypes in the include directory are not made for type checking, which is a pity.
My comment on some of the development is that it seems to be going in the wrong direction, you have three aspects of code production in a MACRO assembler.
1. The mnemonic cruncher, IE, the assembler.
2. The MACRO engine and its capacity to write perfect assembler.
3. The dedicated libraries that can be used with the assembler.
If you maintain this set of distinctions, you can concentrate on the main work which is the assembler where if you start to blur this set of distinctions, you are starting to write a compiler. There is value in providing .IF blocks, .SWITCH blocks, call automation and the like as it improves the throughput of shovelling through high level API and similar styles of code which in turn leaves you with more time to write the stuff that matters, genuinely high speed pure mnemonic code.
Running as open an architecture as possible is the best option for an assembler where restricting the format to produce high level code is a mistake that goes in the direction of a compiler. I see that John and Habran have done some very good work in the development of UASM and I would hate to see it go into the direction of a pseudo compiler, the drift of my comments is make it into a grunty pure "can do" assembler and leave algorithm design to the libraries and macro engine.
Agreed :t
UAsm is an extremely valuable project, as it offers the full functionality of MASM at much higher speed (3x), at a time when Microsoft cripples ML64 to something that can be used by a compiler but sucks from a programmer's point of view.
OPTION LITERALS may be useful for some people, but if my code gets incompatible with assemblers that are still widely used by others, then I may have a problem; if the libraries need to be rewritten (:DWORDs to pointers...), I have a big problem. And there is absolutely no need for this fight: In the rare occasions when I have to pass a literal string to an API, I can use
invoke someapi, chr$("Hello World") ; Masm32
invoke someapi, cfm$("Hello World\x")
invoke someapi, chr$("Hello World") ; MasmBasic
What makes me reluctant at this moment to recommend UAsm (but I still do recommend it!) is this juggling with wild options, and the implicit accusation "why, didn't you read point 3.5.6, options xyz, of that nice manual that I wrote for you?". It is a tool, it is supposed to be compatible with everything I've coded so far with MASM. It should do its job, nothing else. And I fully agree with Hutch: I really don't need yet another C compiler.
:biggrin:
> invoke someapi, chr$("Hello World")
Or write a decent MACRO that allows,
invoke someapi, "Hello World"
It's always a challenge to come up with new features while maintaining the compatibility. That is the main reason for all the extra option settings.
For general use where you may want to be fully masm compatible I'd leave option literals off and use macros instead, we could/should even bundle these into the built-in macro library?
Where I personally saw the literals being useful is when you're writing a lot of custom code that deals with string processing, in which case you can easily switch literals on and then back off again.
OPTION LITERALS:ON
invoke catStr, "result is: ", ADDR resultmsg
invoke replaceItem, ADDR curString, "rd", "road"
invoke replaceItem, ADDR curString, "rod", "road"
invoke replaceItem, ADDR curString, "roads", "road"
and so on.. while it's possible to use the macro method, this a) looks slightly neater and b) re-uses existing string data to reduce data bloat.. so there'd only be a single instance of "road" in this example.
Everything we do we will always try to make work in a way which is either compatible, or extended via an option of some sort.. The problem is at some point, if you start using features it will become incompatible with masm.. like switch, floating point hll comparison, conditional flags, improved union initialization and so on.. I can't see any way around this apart from being knowledgeable enough to know that if you may require that level of compatibility with other assemblers use the features sparingly or not at all.
To say that we shouldn't add these features as it breaks masm compatibility is sort of a bit defeatist, if we do that we cannot add most of the nice to have or useful stuff at all.
We also mustn't forget that we're building up a lot of use on the Linux front where compatibility with masm is non-issue, there we have users who may want us to make it nasm or gas compatible!
You cannot please everyone all of the time :)
Quote from: johnsa on September 06, 2017, 06:58:33 PMTo say that we shouldn't add these features as it breaks masm compatibility is sort of a bit defeatist, if we do that we cannot add most of the nice to have or useful stuff at all.
John,
You and Habran are doing an excellent job, no doubt. And I am not against new features, but one must be careful not to break existing code. For example, a dedicated new macro library is a good thing, but it can be a nightmare if it intrudes into the namespace of an existing library. Imagine, for example, that UAsm supplies a macro library that understands
print str$("The number is %i\n", eax)
This is Masm32 SDK syntax...
This is why the default option should remain "fully compatible, no extra macros".
In terms of the macro library that is ok. The macro library is evaluated before any actual source code, so if you include macros which overlap with stuff in the library it simply replaces the library with your version of the said macro. So as long as the intention and use of the macro is equivalent then it shouldn't affect the outcome. The ones we've included so far are compatible with the implementations from MASM32, granted there are only a few so far but I agree with you 100% if we add a built-in one it should conform so that code written for assembly under ML using MASM32 macros should be identical under UASM with the built-in library. :)
Quote from: johnsa on September 07, 2017, 06:09:11 PMif you include macros which overlap with stuff in the library it simply replaces the library with your version of the said macro.
Sounds ok. How do you handle the case when UAsm has a built-in foo macro, and Masm32 sdk uses
Ifndef foo
foo macro ...
Endif
?
Testcode:
include \masm32\include\masm32rt.inc
.686p
.xmm
ifdef ASDOUBLExxxx
.err <already defined> ; without the xxxx, this error will be triggered
else
ASDOUBLE macro xmmreg
EXITM FP8(1111.1111) ; triggers "not equal"
ENDM
endif
.code
start:
movlps xmm0, FP8(123.456)
movaps xmm3, xmm0
.if (xmm0 == ASDOUBLE(xmm3))
inkey "equal, built-in mlib macro is active"
.else
inkey "user's macro is active"
.endif
exit
end start
This may be virtuous if you are trying to remain compatible with 32 bit MASM but for 64 bit code, either for Windows or Linux you really need a completely different set of macros and here I would be inclined to tweak the macro engine for 64 bit code without having to remain MASM compatible. The old MASM macro engine can be coaxed to do most things with enough dedication but I would imagine that you can do a lot better in a brave new world of 64 bit code.
Agreed Hutch, for now we've just kept the set quite small using the ones that I didn't think would really change much between 32/64. As always I welcome suggestions for inclusions etc.. the 32bit and 64bit macro library implementations are separated out, so we can easily have totally different implementations for each.
In the IFDEF case that JJ mentions I believe that would skip the custom implementation as it would already be defined.
1) Assuming the macros are the same, then there should be no problem.
2) Alternatively, you might have to disable to macro library -nomlib option.
3) We could add a built-in variable which gives the state of the macro library's inclusion and the IFDEF could be extended to check that as well. ?
Quote from: johnsa on September 08, 2017, 06:24:39 PMIn the IFDEF case that JJ mentions I believe that would skip the custom implementation as it would already be defined.
1) Assuming the macros are the same, then there should be no problem.
2) Alternatively, you might have to disable to macro library -nomlib option.
3) We could add a built-in variable which gives the state of the macro library's inclusion and the IFDEF could be extended to check that as well. ?
1) right, but unrealistic - why build your own macro if there is one that works fine?
2) that would disable the whole UAsm macro lib
3) more precisely, let IFDEF believe that the built-in macros and constants are undefined (I can't see a case where that would cause problems)
This is certainly an exotic problem, but MASM has a known namespace that hasn't changed for decades. Extending that namespace with a user's macro library like the Masm32 macros.asm or MasmBasic is one thing, hard-coding new names into the assembler itself is a different thing.
We can use now a new feature in UASM: UNDEF 8)
one example:
IFDEF FP4
UNDEF FP4
ENDIF
and then change it as we want
however, it is not necessary in this case because you can write your own FP4 which will override the one from the macrolib. I have just given an example of UNDEF usage
Undef is a nice feature, but my concern is a different one: There are moments where you ask "is the macro already defined?", and if the answer is yes, you use it, otherwise you define it and you launch an initialisation process. Anyway, don't bother with that, the -nomlib option will do the job.
Quote from: jj2007 on September 08, 2017, 09:32:47 PM
Undef is a nice feature, but my concern is a different one: There are moments where you ask "is the macro already defined?", and if the answer is yes, you use it, otherwise you define it and you launch an initialisation process. Anyway, don't bother with that, the -nomlib option will do the job.
Assuming we only include macros in the library that have extremely unique names or where the names are common-place have exactly the same result as masm32 familiar users would be expecting then that should be ok. There might be a way to include the macro library stuff in some sort of special scope/namespace so that it's always unique.. that was sort of where I wanted to get to with introducing namespace support in UASM, but even then that wouldn't be masm compatible no matter what namespace resolution operator we use.
You may think I have an unusual view on this subject but if the macro engine can do what MASM in 32 bit does, then it may be useful but I would not cripple it to a 1990 design which masm up to the current 64 bit version has. Have MASM compatibility if you want it but be able to either turn it off OR have extra stuff that MASM never supported. You would not want to emulate MASM in 64 bit so there is no reason why you should restrict UASM to that age of design.
There are things that particularly irked me when setting up macros for 64 bit MASM, to make it more flexible you need to expand macros called by other macros inline rather than do them all before the calling macro. As far as which macros to use, it would be a lot simpler if it was left to which set of macros were used so you could have a MASM compatible set of macros, a more advanced and flexible set of macros and in 64 bit a UASM specific set of macros and none of these need to be embedded in the assembler itself. Leave it up to the punter using the assembler to pick which macros to use.
There is no problem providing macros for the punters to use as separate include files as this allows the punter to write as many of their own as they like but I suggest it is a mistake to embed a set of macros in the assembler itself.