Blog

  • AAA DOS: Chapter 8: Going from DOS to Linux or Windows

    In the unlikely event that you have read the first 7 chapters of this book, I am going to assume you are a pretty hard core computer user. What I can say for sure is that you are the type of person who reads books or blog posts about technical details. DOS is an operating system that tends to only be used by nerds who love reading text and efficient operations at the command line.

    Sadly to say, our kind is dying out. At the time of writing this I am 38 years old and there are few people who remember the old way computers were used. DOS is mostly seen as a dead platform and it is not usually used except by programmers and hard core gamers who still run their favorite games in a DOS emulator. Though I cannot fail to mention that FreeDOS is available as a real DOS system.

    https://www.freedos.org/

    But most people know nothing about DOS because the popular operating systems available today are Windows, MacOS and Linux.

    If you have enjoyed programming in Assembly, I do have some helpful tips on how you can apply most of the same information to start Assembly in Linux.

    As far as Windows or MacOS go, I cannot help you much with that because I don’t use proprietary operating systems if I have a choice. These operating systems don’t allow you to simply load registers and call interrupts to print things on the screen.

    Linux, however, works very much like DOS does. If you know how to load the registers correctly and use a system call, you can print strings of text just like in DOS except MUCH faster because you will be running natively instead of in an emulator as in the DOS examples from the rest of this book.

    I cannot cover the details of installing a Linux operating system because there are many choices. However I recommend Debian because it has been my main distro for years. Therefore, the following two programs that I will show you in this chapter have both been tested to work on my 64 bit Intel PC running Debian 12 (bookworm).

    Remember, although DOS was a 16 bit system, modern Linux processors and distros usually support 32 or 64 bit code. Therefore, I will be showing you a small program using the FASM assembler that prints text using a Linux version of the putstring function. It behaves the same as the DOS version behaves in chapter 2.

    main.asm (32 bit)

    format ELF executable
    entry main
    
    main:
    
    mov eax,main_string
    call putstring
    
    mov eax, 1  ; invoke SYS_EXIT (kernel opcode 1)
    mov ebx, 0  ; return 0 status on exit - 'No Errors'
    int 80h
    
    ;A string to test if output works
    main_string db 'This program runs in Linux!',0Ah,0
    
    putstring:
    
    push eax
    push ebx
    push ecx
    push edx
    
    mov ebx,eax ; copy eax to ebx. ebx will be used as index to the string
    
    putstring_strlen_start: ; this loop finds the length of the string as part of the putstring function
    
    cmp [ebx],byte 0 ; compare byte at address ebx with 0
    jz putstring_strlen_end ; if comparison was zero, jump to loop end because we have found the length
    inc ebx
    jmp putstring_strlen_start
    
    putstring_strlen_end:
    sub ebx,eax ;By subtracting the start of the string with the current address, we have the length of the string.
    
    ; Write string using Linux Write system call. Reference for 32 bit x86 syscalls is below.
    ; https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/#x86-32-bit
    
    mov edx,ebx      ;number of bytes to write
    mov ecx,eax      ;pointer/address of string to write
    mov ebx,1        ;write to the STDOUT file
    mov eax,4        ;invoke SYS_WRITE (kernel opcode 4 on 32 bit systems)
    int 80h          ;system call to write the message
    
    pop edx
    pop ecx
    pop ebx
    pop eax
    
    ret ; this is the end of the putstring function return to calling location
    
    ; This Assembly source file has been formatted for the FASM assembler.
    ; The following 3 commands assemble, give executable permissions, and run the program
    ;
    ;	fasm main.asm
    ;	chmod +x main
    ;	./main
    

    The program above uses only two system calls. One is the call to exit the program. The other is the write call which is the same as the DOS function 0x40 of interrupt 0x21; However, the usage of the registers is not in the same order. However, these registers: eax,ebx,ecx,edx are the same registers except that they are extended to 32 bits. That is why they have an e in their name.

    But if you take the time to study it, you will see that it does the exact same process of finding the length of the string by the terminating zero and then loading the registers in such a way that the operating system knows what function we care calling, which handle we are writing to, how many bytes to write, and where the data is in memory which will be written.

    Next I will show you the 64-bit equivalent that works the same way but uses different numbers for the system calls.

    main.asm 64 bit

    format ELF64 executable
    entry main
    
    main: ; the main function of our assembly function, just as if I were writing C.
    
    mov rax,main_string ; move the address of main_string into rax register
    call putstring
    
    mov rax, 60 ; invoke SYS_EXIT (kernel opcode 60 on 64 bit systems)
    mov rdi,0   ; return 0 status on exit - 'No Errors'
    syscall
    
    ;A string to test if output works
    main_string db 'This program runs in Linux!',0Ah,0
    
    putstring:
    
    push rax
    push rbx
    push rcx
    push rdx
    
    mov rbx,rax ; copy rax to rbx as well. Now both registers have the address of the main_string
    
    putstring_strlen_start: ; this loop finds the lenge of the string as part of the putstring function
    
    cmp [rbx],byte 0 ; compare byte at address rdx with 0
    jz putstring_strlen_end ; if comparison was zero, jump to loop end because we have found the length
    inc rbx
    jmp putstring_strlen_start
    
    putstring_strlen_end:
    sub rbx,rax ;rbx will now have correct number of bytes
    
    ;write string using Linux Write system call
    ;https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/#x86_64-64-bit
    
    mov rdx,rbx      ;number of bytes to write
    mov rsi,rax      ;pointer/address of string to write
    mov rdi,1        ;write to the STDOUT file
    mov rax,1        ;invoke SYS_WRITE (kernel opcode 1 on 64 bit systems)
    syscall          ;system call to write the message
    
    pop rdx
    pop rcx
    pop rbx
    pop rax
    
    ret ; this is the end of the putstring function return to calling location
    
    
    ; This Assembly source file has been formatted for the FASM assembler.
    ; The following 3 commands assemble, give executable permissions, and run the program
    ;
    ;	fasm main.asm
    ;	chmod +x main
    ;	./main
    
    

    You may notice that the 64-bit program also uses the syscall instruction rather than interrupt 0x80. On my machine both programs behave identically because both calling conventions are valid. There are executables that run in 32 bit mode and others that run in 64 bit mode. They are not usually compatible and the FASM assembler has to be told which format is being assembled.

    FASM has been my preferred assembler for a long time because unlike NASM, it has everything it needs to create executables without depending on a linker.

    “What is a linker?” You might be asking. You see, the developers of Linux never really expected for people to be writing applications entirely in assembly. Usually they are written in C and then GCC compiles it to assembly that only the Gnu assembler (informally called Gas) can assemble and then link with the standard library. There is a linker program called “ld” that GCC automatically uses.

    However, through some research and experimentation, I have converted the previous 64 bit FASM program into the Gas syntax. As you read it, remember that the AT&T phone company made this weird alternative syntax. The source and destination have been flipped so you will see the register receiving data on the right side instead of the left.

    main.s (GNU Assembler 64 bit)

    # Using Linux System calls for 64-bit
    # Tested with GNU Assembler on Debian 12 (bookworm)
    # It uses Chastity's putstring function for output
    
    .global _start
    
    .text
    
    _start:
    
    mov $main_string,%rax # move address of string into rax register
    call   putstring      # call the putstring function Chastity wrote
    mov    $0x3c,%eax     # system call 60 is exit
    mov    $0x0,%edi      # we want to return code 0
    syscall               # end program with system call
    
    main_string:
    .string	"This program runs in Linux!\n"
    
    putstring:            # the start of the putstring function
    push   %rax
    push   %rbx
    push   %rcx
    push   %rdx
    mov    %rax,%rbx
    
    putstring_strlen_start:
    cmpb   $0x0,(%rbx)
    je     putstring_strlen_end
    inc    %rbx
    jmp    putstring_strlen_start
    
    putstring_strlen_end:
    sub    %rax,%rbx # subtract rax from rbx for number of bytes to write
    mov    %rbx,%rdx # copy number of bytes from rbx to rdx
    mov    %rax,%rsi # address of string to output
    mov    $0x1,%edi # file handler 1 is stdout
    mov    $0x1,%rax # system call 1 is write
    syscall
    pop    %rdx
    pop    %rcx
    pop    %rbx
    pop    %rax
    ret
    
    # This Assembly source file has been formatted for the GNU assembler.
    # The following makefile rule has commands to assemble, link, and run the program
    #
    #main-gas:
    #	gcc -nostdlib -nostartfiles -nodefaultlibs -static main.s -o main
    #	strip main
    #	./main
    

    Although I find the GNU Assembler syntax hard to read, the fact that this assembler exists as part of the GNU Compiler Collection means that it is usually available even on systems that don’t have FASM or NASM available.

    It is possible to use NASM also but it can’t create executables and requires linking with “ld” anyway. It is better to just write directly for the GNU Assembler or stick with FASM if you prefer intel syntax.

    However, the beauty is that the machine code bytes from both types of assembly are identical! In fact that is how I got the GAS version. I had to assemble the other version and then disassemble it with objdump to get the equivalent syntax.

    The programs you saw in this chapter only work on Linux, but Linux is Free both in terms of Software Freedom and Free in price too because anyone with an internet connection can download the ISO of a new operating system and install it on their computer as long as they take the time to read directions from the makers of that distribution. In fact Debian, Arch, Gentoo, and FreeBSD (not Linux but very similar) all have great instruction manuals. If you have managed to read this book, then you will have no problem following their stuff.

  • putstring function update 3-22-2026

    int putstring(const char *s)
    {
     int count=0;              /*used to calcular how many bytes will be written*/
     const char *p=s;          /*pointer used to find terminating zero of string*/
     while(*++p){}             /*loop until zero found and immediately exit*/
     count=p-s;                /*count is the difference of pointers p and s*/
     fwrite(s,1,count,stdout); /*https://cppreference.com/w/c/io/fwrite.html*/
     return count;             /*return how many bytes were written*/
    }
    

    The putstring function is the foundation of chastelib because being able to output something to the screen is important. This function was written for a consistent interface independent of which programming language or library I am using. It manually finds the length of the string and then writes it to standard output.

    This update to the tiny function includes detailed comments nicely lined up. I also changed the return type to an integer for reasons that will become apparent in other programs. Keeping track of how many bytes are printed is now possible by capturing the return value. Of course, if I don’t need this, I ignore it and then it has the same functionality as the original void function.

    Although most nerds won’t understand the need for this, it is written for clarity of how I understand C strings as character arrays. They are best handled with raw pointers and that is why C and C++ are supreme in my opinion because they allow this. In a future post, I may explain the relevance this also has to do with the ncurses library which I have been messing around with lately. Each day I am thinking about a text based game I want to write.

  • Everlasting Love Episode 24: What Does it Mean to Trust God?

    Judena and Chastity talk about the different meanings of faith and trust. These things can sometimes be confusing but become clearer when understanding who a person is, even if that person is God.

    And for some, God is not always human but may be something else they can trust when they can no longer trust humans.

  • Age Verification Rant

    As a Free Software and Open Source advocate, I am always aware of the latest technology changes. In March of 2026, I found several articles and visuals detailing laws that people were trying to pass to force operating systems to have “age verification” built into them. I should not have to tell you my opinion on this because it should be obvious.

    The goal of these laws is to force people to prove that they are 18 years or older to be able to use their computers. As someone who grew up with old computers running DOS, Windows 3.1, Windows 98, and Ubuntu Linux, all before I was 18, I have to say that I oppose such laws because they prevent kids from learning how to use computers at an early age.

    People who are in favor of these laws claim that they are protecting children from harmful things. Don’t fall for this lie. No additional software changes are needed. Parents are ultimately in charge of the computers they buy for their kids and installing parental controls on them if they wish. Also, many websites require users to be 13 years or older to create things like a Facebook account. At some point, these children and especially their parents need to be responsible for following the rules.

    I am not against age verification in principle, but I have to consider the facts. In many cases, age verification will require users to provide photo IDs or Driver’s Licenses to access services we depend on. AI software for reading these already exists for many websites.

    If the government just decides that your state ID or driver’s license is nullified and invalid, this means you can no longer do what others do. See the situation in Kansas for why I, as a Transgender person, am concerned with the evil things governments can do on a whim.

    https://www.nbcnews.com/news/us-news/kansas-revoked-drivers-licenses-1700-transgender-residents-rcna262120

    But laws like the recent one in California go a step further and want to make age verification part of the operating system.

    https://leginfo.legislature.ca.gov/faces/billTextClient.xhtml?bill_id=202520260AB1043

    If you are on a PC or cell phone using software by Microsoft, Apple, or Google, you will not experience any change because these operating systems already lock people out if they don’t have money to buy things in the app stores or a cell phone that can receive text messages. In most cases, only adults have access to cell numbers and email addresses due to the fact that email providers now force people to verify with their phones.

    Side note: The two-step cell phone text verification is a crime against my own mother, who cannot operate a cell phone and has to have my help to get into her own email sometimes. I have also been kicked off my own email several times and had to use my phone. Digital ID is already here because nobody is allowed to do literally anything without a cell phone these days. People can’t even work at Walmart without a cell phone anymore because everything requires the MyWalmart app, which uses the same verification. If my cell phone is lost or stolen, I can’t clock in to work, can’t check my bank account, order an Uber ride, or even call my mom to tell her I am alive. Though at least I can walk since we are both in Lee’s Summit.

    I am a 38-year-old adult who used computers long before I even had internet access. My own response to these evil actions is to censor and restrict people from using their own computers. The biggest target that will be hurt is the Linux operating system because Linux is all about Freedom of software and privacy. The laws passing in some states can make it illegal to install or distribute an operating system without these age verification signals, constantly letting the government and all foreign enemies know who you are and how old you are, because they have your photo ID, which may or may not be valid depending on how transgender you are at the time.

    My cell phone controlling my life is something I can’t do anything about, but nobody touches my Linux PC, where I write my books and do my own programming for the pure love of math. These draconian laws basically make the past 30 years of my life using computers illegal.

    But you know what? It’s gonna be funny when I go to prison and am placed in a room full of rapists, murderers, and people who did nothing wrong but were accused of things because of their skin color. They will ask me: “What are you in for?”

    And I will tell them, “I used Linux and wrote several books and hundreds of fun programs.” Then they will ask me what Linux is. If you feel bad because you don’t know what Linux or the GNU project is, keep in mind that these lawmakers don’t have a clue either.

  • The Intersection of My Religion and My LGBTQIA+ Activism

    The Question Hook

    “Have you ever been told that you have to choose between your soul and your self? For years, I was warned that my identity and my faith could never occupy the same room. But what if the gap between scripture and advocacy isn’t a canyon we fall into, but a bridge we build?”

    The idea that I had to choose between being a Christian and admitting that I was transgender was strange to me, but it is what other humans seemed to imply. I am too smart to think that other people or God can be fooled by dishonesty. A person who is of the LGBTQIA+ spectrum has the choice about whether to LIE about their feelings, but they can’t change them. Those who come out of the closet are just being honest with themselves and others, which, in my opinion, is always less sinful than the alternative of coming up with new lies.

    Although some claim that their faith caused a change in their gender identity or sexual orientation. I think these are not something the individual does but is forced to undergo over time. Either they are pleasing people and trying to conform to what their church teaches them, or perhaps being gay or transgender doesn’t seem to matter as much when they learn their purpose in life is better served as a single person who can do with fewer friends to influence them in the wrong direction.

    The Universal Code

    “In computing, a binary system uses ones and zeros to build infinite worlds, yet we treat the gender binary as a cage. What if God’s mind isn’t a simple ‘either-or,’ but a complex digital landscape? Understanding this logic didn’t just save my faith—it revealed how my advocacy is the ultimate prayer.”

    There have been moments when I almost feel I see something supernatural and beyond anything I was taught about God or the power of the soul. When I am deep into math algorithms used in my computer programs, I sometimes am shocked by the idea that math is a Universal Language, which is at least partially represented by programming languages and the traditional math notation used by physicists and other mathematicians. Humans may have invented the symbols used, but they never could have created numbers, colors, or geometric primitive because these things must exist before anything else can exist.

    Many religions cannot agree on how many gods there are or whether the one Christian God is split into 3 parts. Others like me tend to believe in a dualistic bi-theism where good and evil can only be defined when both exist. Otherwise, the statement that God is good and the devil is bad makes no sense.

    But beyond that, it is important to see that the binary numeral system is the closest way of representing this duality in computers. Perhaps this is why it is the checkerboard or the yin-yang of everything, I believe.

    The Provocative Question

    “What if respecting the identity of the LGBTQIA+ community is precisely what Jesus would have done if he walked the earth in 2026? Most assume faith and advocacy are at war, but I’m deconstructing that myth. Let’s reconcile tradition with authenticity to prove these worlds are beautifully and inherently compatible.”

    When looking at the character of Jesus. He spent a lot of time around the sinners and was often criticized by religious leaders for it. I like to think that Jesus might actually be a better example for people like me than he was for mainstream heterosexual and cisgender people.

    After all, if Jesus is God, and humans, both male AND female, are made in the image of God. Then clearly God is not simply a man or a woman. Even if he presented as a man two thousand years ago, this says very little about what he truly was before he came to inhabit a human body. The pronoun he is only a convenience and tradition, but I would not call it a reality, especially when I don’t identify with my birth sex because it never felt right.

    Of course, much of this is speculation, but I think it is fair to make connections to modern topics that were not discussed in ancient times but are relevant today. In fact, none of the things in the Bible match our modern society. There were no cars, airplanes, or computers in the ancient Middle East. The English language didn’t even exist back then.

    But there is no doubt that gay, transgender, and intersex people would have existed during Jesus’ time. The closest mention of it is what he said about eunuchs.


    "9 And I say unto you, Whosoever shall put away his wife, except it be for fornication, and shall marry another, committeth adultery: and whoso marrieth her which is put away doth commit adultery.

    10 His disciples say unto him, If the case of the man be so with his wife, it is not good to marry.

    11 But he said unto them, All men cannot receive this saying, save they to whom it is given.

    12 For there are some eunuchs, which were so born from their mother’s womb: and there are some eunuchs, which were made eunuchs of men: and there be eunuchs, which have made themselves eunuchs for the kingdom of heaven’s sake. He that is able to receive it, let him receive it." – Matthew 19:9-12


    Clearly, some of us were born different. I would argue that the LGBTQIA+ people were what Jesus was referring to, although the language we use today didn’t exist back then. Even if it had, we can assume most of Jesus’ audience were cisgender and heterosexual people. Those of us who are not like the majority must find our own path.

    And the final question that I think about every day is: Am I a eunuch for the kingdom of heaven’s sake? I am not sure what it means, but I can’t help but feel it is relevant in some way that I don’t have the education to understand.