6

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
[-] avidya@programming.dev 4 points 1 day ago

Check out GLIBC, the standard libc implementation for GNU/Linux, or the easier to read, minimalist, alternative libc MUSL.

Bootlin, runs the Elixir Code Cross Referencer that lets you easily hop between files. For instance, Here is the code for printf in GLIBC.

[-] avidya@programming.dev 2 points 3 weeks ago

If I am not mistaken, the argument made by papers like "C is not a low level language" is that C used to be a low level language, because it fit the architecture of a PDP, but a modern computer isn't a PDP, and so C isn't low level.

13

An intresting talk on Is Everything a File, IO Models, Is C a Low Level Language, and a quick comparison on Interfacing with USB devices on Mac OS, Linux and Windows.

[-] avidya@programming.dev 2 points 4 weeks ago* (last edited 4 weeks ago)

Did you know that

	int history[10] = {0,0,0,0,0,0,0,0,0,0};  

is the same thing as

        int history[10] = {0};

And an idom in C would be to define a constant for the size like this

enum { HISTORY_MAX = 10};
int history[HISTORY_MAX] = {0};
int history_limit = HISTORY_MAX;

avidya

0 post score
0 comment score
joined 1 month ago