Lately, I have been toying the Microsoft Assembler (MASM), and solving small programming challenges in it to learn about it how works. I typically use the GNU AS assembler because its so portable across instruction sets, and open source.
MASM is really interesting because unlike GNU As, which is simply a target for gcc, MASM is from an era where programmers were the target user. To that end, MASM ships with a lot of interesting features designed to improve the experience for the user including an advanced macro system including control flow logic, a type system, macro’s to build function stack frames, and call other functions. Sadly, with 64-bit assembly, some of the magic has been lost (.invoke macro abandoned).
Here is an example program I wrote with MASM to solve a Challenge to order digits in a number in reverse.
There is a UASM project that brings some of this to Linux, including support for (.invoke) macro calling functions with the SYS-V ABI.
Post your favorite assembly tools, your experiences with MASM, and what kind of Macro systems you use if any. Should I learn M4 to bake on top of GNU AS?
.CODE
option casemap:none
option prologue:PrologueDef
option epilogue:EpilogueDef
public maxpermute
;;
; @brief Permute the digits of the number such that number returned as digits
; in descending order
maxpermute proc n:qword
local digit_arr[10]:byte
; prologue automatically written
xor eax,eax
cmp rcx, 0
jz @out
; save
mov [RBP+24], rdi ; save in shadow of rdx
mov n, rcx ; save n in shadow space
; zero the digit count array (al=0 here already)
lea rdi, digit_arr
mov ecx, sizeof digit_arr
rep stosb
; Walk the number computing digits
mov rax, n
@@:
xor edx, edx ; zero edx
mov ecx, 10
div rcx ; edx contains next digit
inc BYTE PTR [digit_arr+rdx]
test rax, rax
jnz @B
; Process the digits in descending order
xor rax, rax ; accumulator
mov ecx, 9; offset to last digit
@outer:
movzx rdi,BYTE PTR [digit_arr +rcx] ; fetch digit count
@inner: ; apply 10*acc + digit transform , rdi times
test rdi, rdi
jz @continue_outer
mov r8, rax
shl r8, 3
lea rax, [rax*2]
add rax, r8
add rax, rcx
dec rdi
test rdi, rdi
jnz @inner
@continue_outer:
loop @outer
mov rdi, n
@out:
ret
maxpermute endp
END

