in reply to Assembly language

Perl has very little to do with assembly language. Assembly language is machine-specific, while perl is designed to run on any platform. If you write an assembly program for Linux, it won't run on DOS or Windows. So, even if the program is designed to do a very simple task such as calculate the value of PI. No file access needed. No internet access needed. No libraries have to be loaded. Just do a bunch of calculations and print the result to the screen. This assembly program will be fast, but it will only run on one specific OS. If you want it to run on just about any computer, then you should write it in Perl. If your goal is speed, then write it in assembly. If you want the calculations to happen inside a web browser upon visiting a website, then you should write it in JavaScript.

I like Perl, because it allows me to write programs that run on both Linux and Windows. And I am right now transitioning from using Windows to Linux. What better way to become familiar with Linux than to learn how to program Linux! It's like having a foot in the door. The cool thing about Perl is that if you are a perl programmer, you have full control over DOS, Linux, Windows, OSX, and you can also be a backend developer! Just have to learn ONE language. That's all.

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

    "If you write an assembly program for Linux, it won't run on DOS or Windows. So, even if the program is designed to do a very simple task such as calculate the value of PI. No file access needed. No internet access needed. No libraries have to be loaded. Just do a bunch of calculations and print the result to the screen. This assembly program will be fast, but it will only run on one specific OS. If you want it to run on just about any computer, then you should write it in Perl"

    Yet more fundamentally flawed advice, given your recent postings I'm not sure if you are just trolling.

    Update: your home node states "The very first programming language I learned was QBASIC when I was 12 years old. Then I was taught C and x86 assembly", how this can link up with your claims above is beyond me.

      Okay, let me prove my point. Here is a little assembly program that displays the message "Hello World" in the terminal window. That's all it does. Nothing complicated. It's the equivalent of print "Hello World"; in perl.

      The interesting thing about this particular asm code is that it will only run on 64-bit Intel and AMD microprocessors. It will not run on a 32-bit CPU. And it will not run on ARM, SPARC, or old iMac processors!

      On the other hand, the print "Hello World"; perl equivalent of this program is not bound to one particular architecture or one particular OS. It would run on any CPU and any OS.

      To further prove my point, if you would run an assembler to convert this asm text code to an obj file and then link the obj into exe file, it would result in a Windows executable. If you tried to run it in Linux, it wouldn't run (without wine). If you tried to execute it on an Apple MacBook Pro, it wouldn't run. It wouldn't run even if you included it in your perl script inline. This code is not only machine specific, but it is OS specific. That's what I meant. It's a fact. Try it if you don't believe me.

      A simple print "Hello World" perl script will run on any computer, but once you insert asm code into your perl script as inline assembly, chances are you have limited your perl script to one particular processor and one particular OS! Now, your perl script is no longer compatible with 90% of other computers out there. But if you omit the inline assembly code, then it will run on other computers.

      section .data Message db "Hello World", 0Dh, 0Ah MessageLength EQU $-Message section .text Start: sub RSP, 8 sub RSP, 32 mov ECX, STD_OUTPUT_HANDLE call GetStdHandle mov qword [REL StandardHandle], RAX add RSP, 32 sub RSP, 32 + 8 + 8 mov RCX, qword [REL StandardHandle] lea RDX, [REL Message] mov R8, MessageLength lea R9, [REL Written] mov qword [RSP + 4 * 8], NULL call WriteFile add RSP, 48 xor ECX, ECX call ExitProcess
        This code is not only machine specific, but it is OS specific.

        Yes, you're right about that code being specific to an architecture and OS. However, I think the quibble here is that it's very different from what you originally said:

        Assembly language is machine-specific, while perl is designed to run on any platform. If you write an assembly program for Linux, it won't run on DOS or Windows.

        Stated so generally, that's not correct: some assembly programs can be run on multiple OSes. And I think "machine-specific" is too vague, as that could also be interpreted to mean that assembly code is specific to one particular computer; the Wikipedia quote you gave here is much more accurate. And some of your argumentation unfortunately goes against itself, like here:

        ... it would result in a Windows executable. If you tried to run it in Linux, it wouldn't run (without wine).

        Wine Is Not an Emulator, and there's also the Windows Subsystem for Linux, which you may not have known about, but both these examples contradict your statement "... if you try to execute a Linux program in DOS or vice versa, it won't even load, because the OS does not recognize it as a valid executable." Yes, a compatibility layer is needed, but the assembly is executed natively. I also have to say I think you're muddying things between the concepts of ABI, assembly language, and actual binary processor instructions.

        Another example: in this node you suggest that adding assembly to Perl will make it less portable, which is of course true across processor architectures, and it's true when comparing a Perl program with assembly to one without assembly. But in the same paragraph you mention portability across OSes, and here I'd say that using inline assembly in Perl can actually make the assembly more portable than the same assembly code without Perl. The same is true for assembly embedded in C code, which most if not all C compilers support. Take your initial example:

        So, even if the program is designed to do a very simple task such as calculate the value of PI. No file access needed. No internet access needed. No libraries have to be loaded. Just do a bunch of calculations and print the result to the screen.

        The only thing in that whole program that is OS-specific is the output part. If all the assembly had to do was return that value in memory to Perl instead, and Perl does the printing, then suddenly you have portability across all OSes on the same processor architecture (that Perl runs on; another point you gloss over in your various posts). See the example in the synopsis of Inline::ASM, for example.

        Don't get me wrong, when it comes to 80386 assembly, I think you know your stuff. Rereading your posts here, I also understand the points you were trying to make. Here you said "You know what I am talking about," and yes, we know what you're talking about. But remember that this is all taken in the context of helping newcomers: making over-generalized statements, sometimes conflicting and/or inaccurate ones, can muddy the waters and cause confusion, and potentially be more damaging than helpful. I would suggest being more careful with the language you use to explain things.

        You bound this to windows by using things WriteFile, did you made a copy/paste error because you don't import (extern) the Windows API functions (WriteFile, GetStdHandle or ExitProcess). If you write OS specific code obviously it will only work on that OS. Assembly can be used to create a 'hello world' for any CPU, regardless of OS. You could write perl code which will only work on certain OS. Assembly can run on a bare CPU, stated many times in the thread, stop talking round this. You make it sound like your way is the only way, and the right way, buddy it's not. These are bad habits, arguing against yourself, contradicting yourself, detailing threads, confusing OP by changing the terminology in different posts.
Re^2: Assembly language
by stevieb (Canon) on Dec 14, 2019 at 18:33 UTC
    "Perl has very little to do with assembly language"

    This is wrong as well.

    *All* high-level languages are compiled into assembly/machine code to be understood by the processor(s).

    "If you want it to run on just about any computer, then you should write it in Perl. If your goal is speed, then write it in assembly."

    If you want to run something on any computer, use any language that can compile into machine code for the specific CPU architecture you're targeting.

    If your goal is speed, write it in a compiled language (eg. C) instead of a scripting language.

    If your goal is to write something that is so low-level that there isn't a compilation routine to do accurate translation, write it in assembly.

Re^2: Assembly language
by LanX (Saint) on Dec 14, 2019 at 18:25 UTC
    > If you write an assembly program for Linux, it won't run on DOS or Windows.

    That's plain wrong.

    Both operating systems can run on the same CPU.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      "If you write an assembly program for Linux, it won't run on DOS or Windows.

      That's plain wrong.

      No, it's not wrong. (Please re-read what I wrote, and then read what you wrote. We're talking about two different things. You totally I mean TOTALLY misunderstood my statement! And you're responding to a statement that I never meant to write.)

      DOS programs call INT 21h. In Windows programs, there's the Windows API, and Linux has its own service libraries. The way the EXE headers are written in Windows is totally incompatible with Linux headers. And if you try to execute a Linux program in DOS or vice versa, it won't even load, because the OS does not recognize it as a valid executable. You know what I am talking about, so don't pretend that this isn't true.

        You seem to be confusing an "executable" with "assembly", probably because they both deal with machine code.

        The way how the result of an assembler is bound to needed libraries to create an OS specific executable is irrelevant.

        Anything else compiling to machine like C or Pascal needs this step too.

        I can even include the same ASM code inside Perl code via Inline::ASM and start it under different OS, as long as it's the same CPU.

        > Please re-read what I wrote,

        I did.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re^2: Assembly language
by SkinBlues (Acolyte) on Dec 14, 2019 at 18:33 UTC
    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?

      It's definitely fundamental. Assembly is machine code, the lowest level code a computer processor can understand directly. It's the foundation of all high(er) level programming languages, including scripting languages such as Perl.

        Assembly is not machine code. It doesn't help newcomers to this stuff to blur the distinction. Assembly is a symbolic language that has a very close to 1:1 mapping with machine instructions, though not exactly 1:1. But it provides named constants, named registers, named machine instructions, labels, memory addressing strategies, and a lot more that are not native to machine code. Assembly language is a human readable language, and cannot be run natively on the CPU any more than native machine instructions can be read by a human (without at very least first converting them to an unambiguous printable encoding such as hex -- but even then, good luck with that for anything that isn't super trivial.

        Assembly is useful as a teaching aid, or for programming very small systems that don't have C compilers available. It might be useful for hand-optimizing tight sections of C code. But on modern computer hardware, the need for hand-optimizing code at the Assembly level is quickly vanishing.

        I enjoyed learning 6502 Assembly. On the one hand it was a big pain. But on the other, it was fascinating. But even in the 80s, it was just about the slowest way to get anything done. I think that if someone wants to learn assembly, they should do it. They'll gain an appreciation for the fundamentals. But nobody's going to write a REST microservice in it. ;)

        To the OP: The days of being able to just input raw machine instructions for the CPU to execute ended with computers with switchboard face panels like the Altair 8800. And even then, it was hard enough that people would mostly just key in a short bootloader, and use it to pull down the actual program, written in a less tedious way. Nowadays, when you're typing at the Linux command line you are typing within a piece of software (the shell), and it doesn't expose the CPU directly, at least not easily. The shell doesn't understand 011101011101000101001010100001010111110101010000000101010101011011010110101.


        Dave

      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; }

        "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.

        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)