[–] 2 points 3 weeks ago* (2 children)

You can actually change this.

The compiler has an 'execution' character set that describes how characters should be interpreted at run time, and a 'source' character set, and they need not be the same.

Check this out

$ cat test_ebdic.c ; gcc -fexec-charset=EBCDIC-US test_ebdic.c ; ./a.out | xxd
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
        char data[] = "Hello";
        printf("%s\n", data);
        return EXIT_SUCCESS;
}
00000000: c885 9393 960a                           ......

The file was typed in UTF-8, and the compiler automatically translated the literal to EBCDIC-US to emit at run time. My terminal can't display this, so I view it with a hex editor.

  • source
  •  

    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
    
    [–] 4 points 1 month 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.

  • source
  • [–] [S] 2 points 2 months ago (3 children)

    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.

  • source
  • parent
  • context
  • [–] 2 points 2 months ago* (2 children)

    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;
    
  • source