in reply to Re^2: Assembly language
in thread Assembly language

My understanding is that assembly language is a more simpler, fundamental language than languages like Perl and Javascript. Is that right? How could I write a program in assembly language?

Yes, assembly is the most fundamental level. To write assembly programs, you need a compiler ((correction: you need an assembler)) that translates your human readable text file into binary code that runs on either DOS, Windows, Linux, OSX, or the boot sector. You need to pick a platform first. Each of these environments requires your program to work slightly differently, so you can't just write an assembly program that will work on all computers and all platforms. That's what I meant earlier when I said it is machine specific and OS specific. There are different processors. 64-bit processors use different assembly instructions than 32-bit processors. Cell phones use different instructions. There are various processors, and you have to decide which one you want to study first.

I studied the Intel 80386 processor myself, and I wrote programs for DOS and the boot sector. And in order to do that, you have to download a program called A86.COM. To write Windows assembly programs, you can download FASM.EXE or something similar. In Linux, I am not sure what you would use. I encourage you to ask more questions. Do more research.. Until then, here is a simple assembly program which I wrote for DOS (16-bit):

; ; This program can add two very large unsigned integers. ; The program must receive two numbers in base 10 as ; parameters, and it prints the result to STDOUT. ; The biggest number you can possibly end up with has ; 125 digits. This limit is because DOS parameter string ; is stored in a 127-byte string space starting at DS:0081H. ; Written by Zsolt in Dec 15, 2018. ; ; ; To compile & run, enter the following commands: ; ; C:\>TASM ADD ; ; C:\>TLINK /t /c /x ADD ; ; C:\>ADD 3333 55555 ; 58888 ; C:\> ; ; ; CODE SEGMENT ASSUME CS:CODE, DS:CODE, ES:CODE, SS:CODE ORG 256 MAIN: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; See if we've got any parameters. PUSH CS POP DS ; DS <- CS PUSH CS POP ES ; ES <- CS MOV SI,00080H ; SI <- points to parameter string length MOV DI,OFFSET ARGS ; DI <- points to ARGS parameter table LODSB CMP AL,3 ; Parameter string must have at least 3 bytes JB No_Number ; Save the first two parameters. ; (SI now points to the first character of the parameter string.) CALL GrabArgument ; Get first number CALL GrabArgument ; Get second number JMP Add_Numbers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; This function finds the next word in the parameter ; string and saves a pointer for future reference. ; Also, it saves the length of the parameter word. ; ; This function populates the ARGS parameter table. ; The ARGS parameter table consists of 4-byte objects. ; The first 2 bytes are the length of a word, followed ; by a 2-byte pointer to the last letter of word. ; If the word contains anything other than digits (0-9), ; then the program ends prematurely. ; ; DS:SI <- pointer to parameter string ; ES:DI <- pointer to ARGS parameter table ; ; This function increments SI and DI. ; GrabArgument: XOR CX,CX CLD NextChar: CMP SI,0100H ; DOS parameters cannot be longer than 128 byte +s JAE No_Number LODSB CMP AL,13 JE No_Number ; End of string? CMP AL,32 JBE NextChar ; Skip whitespace ; We continue this way only if we've got something ; other than a space or tab. ; Normally in C language, pointers always point to the ; first character of a string, but in this program, ; parameter pointers will point to the last letter ; of a string, because we start adding numbers ; from right to left. CountLen: INC CX ; Count the length of string LODSB CMP AL,32 JBE End_of_Number CMP AL,'0' JB No_Number CMP AL,'9' JBE CountLen No_Number: MOV DX,OFFSET About JMP Print_and_Exit End_of_Number: XCHG CX,AX STOSW ; Save string length DEC SI MOV AX,SI DEC AX STOSW ; Save ptr to the end of string RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Prepare for addition. ; Add_Numbers: ; Figure out which number is longer. MOV SI,OFFSET ARGS LODSW ; Load length XCHG CX,AX LODSW ; Skip pointer XCHG BP,AX ; BP = number1 ptr LODSW ; Load next word's length CMP CX,AX ; AX > CX ? JA CX_BIGGER XCHG CX,AX CX_BIGGER: ; Now CX holds the length of the longest string. LODSW XCHG SI,AX ; SI = number2 ptr MOV DI,OFFSET Result-1 ; DI = destination ; Now we have the following setup: ; SI points to the last letter of the first number ; BP points to the last letter of the second number ; DI points to the last letter of the result XOR DX,DX ; DL = carry flag STD NextDigit: ; START ADDING DIGITS ; ; Here make sure that tonce we get an invlaid value in AL ; invalid digit, we assume all digits are 0 after that. ; or if we're past the end of word. ; CALL GetDigit ; Read from number 1 XCHG BX,AX ; digit -> BX XCHG BP,SI ; Read from number 2 CALL GetDigit ; digit -> AX ADD AL,BL ; Add the two digits ADD AL,DL ; Add carry MOV DL,DH ; Reset carry (DL=0) ADD AL,'0' CMP AL,'9' ; Carry? JBE NO_CARRY SUB AL,10 INC DX ; Set carry (DL=1) NO_CARRY: STOSB ; write result LOOP NextDigit ; Note: DH is always 00. CMP DL,DH ; Is carry set? JE DONE MOV AL,'1' STOSB DONE: MOV DX,DI INC DX Print_and_Exit: MOV AH,9 INT 21H ; Print text MOV AX,4C00H INT 21H ; Exit 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; This function reads the next digit of the number ; into register AL. If we reach the end of the number, ; then AL will be 0, and our pointer (SI) will stay ; in place, otherwise SI will jump to the next digit. ; (Keep in mind we're reading from right to left.) ; ; DS:SI <- pointer to base 10 number string ; AL -> raw value ; GetDigit: LODSB ; digit -> AX SUB AL,'0' CMP AL,10 ; is AL < 10 ? JB ValidRange ; Looks like we reached the end of the number. MOV AL,DH ; AL=0 INC SI ValidRange: RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ARGS contains a 2-byte pointer to a parameter word, ; followed by a 2-byte string length, followed by the ; pointer to the next parameter, followed by its length. ; Initially, ARGS contains 2 pointers to a blank string ; of zero length. ; About DB 10,13, "This program adds two positive integers of any +size and displays the result." DB 10,13, "Usage: ADD <number> <number>", 10,13 DB 10,13, "Example: ADD 19333045834565223108349833745893453 129 +82372388169001", 10,13 DB 10,13, "This program requires two numbers as parameters." DB 10,13, "The parameters may only contain digits (0-9).",10,13 +,10,13 Result DB "$" ; The program will either display the About message, or ; it will display a number. If we display a number, then ; we will overwrite the About message with digits. ARGS DW 0, OFFSET Blank, 0, OFFSET Blank Blank DW 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CODE ENDS END MAIN


Now, here is the same program in Perl. See, how shorter and simpler this is?:

#!/usr/bin/perl -w use strict; use warnings; my $ABOUT = "This program adds two positive integers of any size and d +isplays the result.\n" . "Usage: ADD <number> <number>\n\n" . "Example: ADD 19333045834565223108349833745893453 12982372 +388169001\n\n" . "This program requires two numbers as parameters.\n" . "The parameters may only contain digits (0-9).\n\n"; @ARGV == 2 or die $ABOUT; if (Is_Not_A_Number($ARGV[0]) || Is_Not_A_Number($ARGV[1])) { die $ABOUT; } print ADD($ARGV[0], $ARGV[1]); exit; #################################### sub ADD { my $A = defined $_[0] ? $_[0] : ''; my $B = defined $_[1] ? $_[1] : ''; my $AL = length($A); my $BL = length($B); my $i = ($AL > $BL) ? $AL : $BL; my $CARRY = 0; my $SUM = '0'; my $X; while ($i-- > 0) { $X = $AL ? vec($A, --$AL, 8) : 48; $X += ($BL ? vec($B, --$BL, 8) : 48) + $CARRY; $CARRY = $X > 105 ? 1 : 0; vec($SUM, $i, 8) = $X - ($CARRY ? 58 : 48); } return ($CARRY ? '1' : '') . $SUM; } #################################### sub Is_Not_A_Number { @_ or return 1; my $N = shift; return 1 unless defined $N; my $L = length($N); return 1 unless $L; my $C; while ($L-- > 0) { $C = vec($N, $L, 8); return 1 if ($C < 48 || $C > 57); } return 0; }

Replies are listed 'Best First'.
Re^4: Assembly language
by marto (Cardinal) on Dec 14, 2019 at 19:09 UTC

    "you need a compiler" not true, you need an assembler, not a compiler, this isn't how this works.

    ”Cell phones use different instructions." That would depend on the CPU they used. Few are x86, most are ARM.

Re^4: Assembly language
by SkinBlues (Acolyte) on Dec 14, 2019 at 19:28 UTC
    My mac has a 2.5 GHz Intel Core i5 processor, which I believe is 64bit. I would like to run a very simple script to add two numbers together and output the result. If assembly is fundamental, and machine code is the most fundamental, why would I have to download a program to run it? I do not want to download a program to be able to run it. There should be a way to access the processor directly (possibly through terminal) where I could write "000 101 100 ..." and have it output "101 001" (these numbers do not mean anything real)

      You may take a look at Xcode - if you really want to go over this bridge. A more comfortable alternative (smaller instruction set bla...) might be to buy an Arduino for little money and check out Atmel‘s Studio 7 - because the Arduino IDE accepts only this C/C++ subset as far as i remember. Unfortunately Studio 7 runs only on Windows. Therefore you will also need something like Parallels. Good luck and best regards, Karl

      Update: Lost + Found 😎

      «The Crux of the Biscuit is the Apostrophe»

      perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

        Arduino IDE accepts only this C/C++ subset

        Not true actually, although at times it seems the IDE tries to hide the fact that the tool chain is full on gcc. I use C++ including templates (although I've not used exceptions or RTTI) on Arduino Nanos and related 8 bit machines with 32 kBytes of code space and a couple of kBytes of RAM.

        I find the Setup() / Loop() structure of sketches a real PITA a lot of times because it forces the use of global variables when they should really not be needed. However full points to Arduino for using a real language for a simple cheap teaching machine.

        Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond

      It's fundamental in the sense that assembly doesn't translate into anything else. It is the lowest level machine language to give instructions to a processor. All the major tasks are broken down into the tiniest instructions. And they cannot be broken down into smaller pieces. It's like atoms. Atoms are the most fundamental building blocks of the world. And if you want to mix chemicals and do stuff, you probably need a science lab! But you might say, if they are the most fundamental, then why do I need a sciance lab? Why can't I just mix something in my backyard or in my hand? You can, but most chemical engineers don't do it that way.

      However, if you want to do it your way, in DOS, there's a program for that. It's called DEBUG.EXE. With this program, you can type your assembly code directly into the memory and run it. But I am not sure if Linux or OSX has a similar program. Most programmers, and I mean 99.99% of people type their assembly program in plain text and save it as a text file and then use an assembler to translate the code to machine language. Then they run the executable and watch it in action. Or they may load a debugger and use it to trace through the program to see how it works.

        All the major tasks are broken down into the tiniest instructions. And they cannot be broken down into smaller pieces.

        Whether that is true or not depends on the processor: Intel Microcode.

        Update: "... they cannot be broken down into smaller pieces. It's like atoms. Atoms are the most fundamental building blocks of the world." is wrong in a similar way: Subatomic particle.

        "then use an assembler" a few moments ago you said a compiler was required..