Take This Life

Take This Life (https://www.takethislife.com/)
-   Science and Technology (https://www.takethislife.com/science-technology/)
-   -   Assembly programming (https://www.takethislife.com/science-technology/assembly-programming-287836/)

Ehisdi 07-15-18 11:15 PM

Hoo boy, I'm in so much pain, and I doubt I'll be able to explain this bit of code all that well, but here goes.


;  #1                                      #2                                        #3
 itobf:                                  itobf:                                    itobf:                     
    DEC        RDX                          AND          DL , 1111b                    AND          DL , 1111b
    ADD        RDI , RDX                                                                                       
    INC        RDX                          MOV          CL ,  DL                      MOV          CL ,  DL 
    SHL        RDX ,  2                    SHL          CL ,  2                      SHL          CL ,  2 
    ADD        RDI , RDX                    ROR        RSI ,  CL                      ROR        RSI ,  CL     
    MOV BYTE  [RDI],  0                itobf_begin:                              itobf_begin:             
    DEC        RDI                          XOR        EAX , EAX                      XOR        EAX , EAX 
 itobf_begin:                            itobf_genword:                                MOV          CL ,  4
    XOR          AL ,  AL                    SHL        RSI ,  1                  itobf_genword:           
    SHR        RSI ,  1                    ADC          AL , 0x30                    SHL        RSI ,  1
    ADC          AL , 0x30                  ROR        EAX ,  8                      ADC          AL , 0x30
    MOV BYTE  [RDI],  AL                                                              ROR        EAX ,  8
    DEC        RDI                          SHL        RSI ,  1                                                     
    DEC          DL                          ADC          AL , 0x30                    DEC          CL                         
  TEST          DL ,  DL                    ROR        EAX ,  8                    TEST          CL ,  CL 
    JZ        itobf_ret                                                              JNZ        itobf_genword
  TEST          DL ,  3                    SHL        RSI ,  1                      DEC          DL           
    JZ        itobf_write_delem            ADC          AL , 0x30                                                   
    JMP        itobf_begin                  ROR        EAX ,  8                      MOV DWORD  [RDI],  AX   
 itobf_write_delem:                                                                    ADD        RDI ,  4
    MOV BYTE  [RDI], ':'                    SHL        RSI ,  1                                                   
    DEC        RDI                          ADC          AL , 0x30                    TEST          DL ,  DL   
    JMP        itobf_begin                  ROR        EAX ,  8                      JZ          itobf_ret   
 itobf_ret:                                  DEC          DL                            MOV BYTE  [RDI], ':'
    RET                                                                                INC        RDI
                                            MOV DWORD  [RDI], EAX                      JMP        itobf_begin
                                            ADD        RDI ,  4                  itobf_ret:
                                                                                        MOV BYTE  [RDI],  0
                                            TEST          DL ,  DL                      RET                     
                                              JZ          itobf_ret                 
                                            MOV BYTE  [RDI], ':'                                         
                                            INC        RDI                                         
                                            JMP        itobf_begin                                         
                                            MOV BYTE  [RDI],  0                                         

I haven't tested #3, so I don't know if it works or not, it should, but meh, it wasn't meant to work, just a modification of #2 to show it with less code.

As for which one I'm sticking with, I'm sticking with #2 as it's quicker than the rest, and it's a good one for showing how writing multiple lines which do the same thing is far superior to using loops. (I won't explain how, as I'm just too exhausted from this pain, but trust me, :thumbsup:)

#1 took me most of today to write, and #2 only took me a few minutes, #3, about a minute or two.

What this code does, is it translates an integer into a binary representation along with a string delimiter, so the following would take place for a number 34979.


itobf(str, 34979, 4); str = "1000:1000:1010:0011"
itobf(str, 34979, 3); str = "1000:1010:0011"
itobf(str, 34979, 2); str = "1010:0011"
itobf(str, 34979, 1); str = "0011"

(Woops, just noticed the "AND DL, 1111b" is wrong. It should be "AND DL, 111b", and I should "DEC DL" to ensure that only up to 4 bytes are read.

DEC DL    ; Ensure that if 8 is passed, it becomes 7, which equals 111b
AND DL , 111b    ; Make sure DL is not greater than 7.
INC  DL              ; Increment DL to ensure all whole four bytes can be read.

Yeah, in way too much pain. I can't concentrate beyond this. Well, hope someone likes it.

EmpatheticThoughts 07-17-18 09:50 PM

I like it lol
And I hope you feel better soon! :hug:

Ehisdi 07-18-18 11:08 PM

Oh-kay! I revamped my itob routine, it's a bit longer than the old one, but it's still pretty quick.


; itob( char * source, int A, int len)

    MOV          AX , 0x30          ; Setup first character.
  TEST          DL ,  DL          ; Is length used?
    JZ        itob_skip_init_dl
    MOV          CL ,  DL          ; Setup length.
    ROR        ESI ,  CL          ; Rotate that bastard.
    ROL        ESI ,    1
    JMP        itob_l              ; Go ahead and start reading.

itob_skip_init_dl:                  ; We're using the entire integer.
    MOV          CL ,  33          ; We're going to read the whole integer.
itob_find_first_c:                  ; Find first carry bit.
    DEC          CL
    JZ        itob_ret            ; If 0, then write '0' and call it good.
    ROL        ESI ,    1          ; Find our carry.
    JNC        itob_find_first_c

itob_l:                            ; Now we can create that bloody string.
    ADC          AL ,    0          ; Create our character.
    DEC          CL
    JZ        itob_ret            ; Length found, get outta here.
    MOV BYTE  [RDI],  AL          ; Write our current character.
    INC        RDI                ; Prepare for next character.
    MOV          AL , 0x30          ; Reset our new character
    ROL        ESI ,    1          ; Get next bit.
    JMP        itob_l              ; Redo all this crap.
    MOV WORD  [RDI],  AX

This one will restrict the size of the integer read by the variable len, and pad with zeroes. If len = 0, then the entire integer is read and it is not padded with zeroes.


itob(str, 37, 3); str = "101"
itob(str, 37, 15); str = "000000000100101"
itob(str, 37, 0); str = "100101"

What really blows about this one, I kind of forgot to do the error checking, :confused:. Meh, the pain caused me too much duress and I really really had a hell of a time thinking on this.

Ehisdi 07-20-18 05:13 AM

Still having massive troubles with sleeping, so I decided to revisit my big integer library that I've been trying to re-write in assembly...

So, in order to utilize the stack space, which would allow me to keep a lot of the old code I've already written, as well as make a lot of the work so so soooo much simpler, I've decided to use the following lines of code...


  PUSH RBP            Save RBP
  MOV  RBP, RSP      Save RSP
  MOV  RSP, bigint    Setup bigint to RSP
;  And I have to re-read how the stack space is setup, because I may have to do the following
;  SHL  RCX , 3        Multiply the length of bigint by 8.
;  ADD  RSP , RCX  Add that number to RSP so the stack space starts at the "end".
;                            Of course, I could just ADD, but I may PUSH and POP, too.
;                            Haven't made up my mind yet...O_o.  Hmm?
; ... Do stuff
  MOV RSP, RBP    Restore RSP
  POP  RBP            Restore RBP

And what I've decided to do for dealing with all the data, is generate a "linked list".


a = new_bigint();  // This would create a new bigint, and append it to
                  // the linked list, and 'a' would point to this new number.

Now comes the interesting hypothesis, if realloc is called and the space created moves to a new location, two things may happen with the old memory location, 1. A temporary qword stores the "new" location, and the old qword will read that location to copy data over, or, OR, 2. Backup the pointer to a register/stack/whatever and "trust" that some other program doesn't overwrite that space while the data copying is taking place. (If I can get more sleep and think on this more logically, I may ask about this in one of the programming forums I used to frequent).

Lastly, by utilizing a linked list for storing all the big integers, then the "deconstructor" (free) routine could be written without having to rewrite it every single time.


init_bigint();  // Initialize the linked list, and a temporary number.

a = new_bigint();
// Several lines of code later.
b = new_bigint();
// Even more lines of code later.
c = new_bigint();

free_bigint();  // Free all big integers created...
// This would make the code so much easier to read, as well as it would definitely be a lot cleaner.

End of brain fart...Very very sleepy...Very very sore...

Ehisdi 07-26-18 03:08 AM

Mental note to self: The following code is perfectly fine...(I asked someone in another forum and they concurred).


MOV  reg , [reg]
AND  reg , [reg]
; etc

Ehisdi 08-03-18 12:30 AM

Holy halibuts I'm having such trouble concentrating...

Anyhoo, I got the first macros at least finished.


;  Assembly macros

;backupTo From  #1, #2...
;  Push/Pop #2+ To/From stack, and move stack to #1.
;  Keep order for quick copy/paste within vim.

%macro backupTo 1-*
    %rotate 1
    %rep %0-1
        PUSH  %1
    %rotate 1
        MOV  %1, RSP

%macro resetFrom 1-*
        MOV RSP, %1
    %rep %0-1
    %rotate -1
        POP %1

; mpush mpop    Multi Push and Pop
;    Keep order for quick copy/paste in vim.

%macro mpush 1-*
    %rep %0
        PUSH %1
    %rotate 1

%macro mpop 1-*
    %rep %0
    %rotate -1
        POP %1

This way, I can use the following code (and quick copy/paste within vim).


    backupTo RBP, reg1, reg2, reg3, ...
    ;  ... Do stuff here
    resetFrom RBP, reg1, reg2, reg3, ...

; And

    mpush reg1, reg2, ...
    ; ... Do stuff here
    mpop  reg1, reg2, ...

Ehisdi 10-06-18 10:20 PM

Alrighty! Was able to use some of my mind so I wrote a few things down, and made some hella mods to my Makefile and binary/hex routines.

Note: Need to research .PHONY in a Makefile.

ASMSRC=$(wildcard *.asm)
ASMOBJ=$(patsubst %.asm,%.o,$(ASMSRC))

ASSDBG= -g dwarf2



CFLAGS= -g -Wall

all:        $(ASMOBJ) ccode

%.o: %.asm
        $(ASS) $(ASSFLAGS) $< -o [email protected]

        $(CC) $(CFLAGS) $(CSRC) $(ASMOBJ) -o $(PRGNAM)

        rm $(ASMOBJ) $(PRGNAM)


I think I need to redo my Makefile to reflect the changes to each routine, as a common use Makefile section might prove to be too much...O_o.


;  Defines
;  BINARY_DELEM  Every fourth character in binary
;                  representation will contain this character.
;  _USE_BIN_PREFIX_  use 0b as a prefix.
;  _USE_BIN_SUFFIX_  use b as a suffix.

%define BINARY_DELEM ':'

section .text

    global itobs

;  itobs( src ,  C , len )
;  itobs( RDI , RSI , RDX )
;  len == 0, return a single bit.
;  Registers used:  CL

  AND          DL ,  111111b              ; Ensure <= 64 bits are read.
  INC          DL
  MOV          CL ,  DL                  ; Only CL can be used by ROR.
  ROR        RSI ,  CL

  MOV          AX ,  '0b'
  MOV WORD  [RDI],    AX
  ADD        RDI ,    2

  MOV BYTE  [RDI], 0x30                  ; Write '0' to string.
  SHL        RSI ,    1                  ; test bit.
  ADC BYTE  [RDI],    0                  ; Add 1 if it's a 1 to the '0'.

  INC        RDI                          ; Next char write.

  DEC          DL                          ; Subtract 1 from DL.

    JZ        itobs_exit                  ; Get outta here if DL == 0
  TEST          DL ,  11b                  ; Is DL == 0 ( MOD 4 )?
  JNZ        itobs_loop                  ; If not, continue reading number.
  MOV BYTE  [RDI],  BINARY_DELEM        ; Add our delemeter string.
  INC        RDI
  JMP        itobs_loop                  ; Continue reading number.

  JNZ        itobs_loop


    MOV        AX ,  0x0062
    MOV WORD [RDI],    AX
    MOV BYTE [RDI],    0                ; Write null char.



;  Defines
;  HEX_DELEM  Change the string delimeter.
;  _USE_HEX_PREFIX_ Use 0x for the hexadecimal prefix.
;  _USE_HEX_SUFFIX_ Use h for the hex suffix.
;  _NO_HEX_DELEM_  Do not delimate the hexadecimal string.

%ifdef HEX_DELEM
%ifnstr HEX_DELEM
%define HEX_DELEM ':'

section .text
    global itoxs

;  itoxs( char *src, number, length )
;  itoxs( RDI, RSI, RDX )

    AND          DL ,      1111b      ; < 64 bits.
    MOV          CL ,      DL          ; CL can only be used with RO#
    SHL          CL ,          2
    ROR        RSI ,      CL

    MOV          AX ,      '0x'
    MOV WORD  [RDI],      AX
    ADD        RDI ,        2

    MOV          AL ,      SIL
    AND          AL ,      1111b

    CMP          AL ,      10
    JL          itoxs_less
    ADD          AL ,        7

    ADD          AL ,    0x30
    MOV BYTE  [RDI],      AL
    INC        RDI

    ROL        RSI ,        4

    DEC          DL

%ifdef HEX_DELEM
    JS          itoxs_exit

  TEST          DL ,        1
    JZ          itoxs_loop
    INC        RDI
    JMP          itoxs_loop

    JNS          itoxs_loop


    MOV          AX,      0x0068
    MOV WORD  [RDI],      AX
    MOV BYTE  [RDI],        0


All in all, regardless of the overuse of macros, it's still quite fascinating none-the-less. Plus, it really helps to understand the preprosessor better. I likey very much. I just need more experience with Make files, though.

Ehisdi 10-14-18 10:53 PM

Alrighty! After a lot of "dumb" time, I finally had enough brain umph to research the XMM registers. They're useful for double/single precision numbers, but integers, they're crap. So...I really have no use for them, at least now. So that answers that question, and I can stop fretting about the "what ifs".

Ehisdi 11-11-18 01:47 AM

And or xor not shl shr ror rol
The instructions I'm going to write about are the following, AND, OR, XOR, NOT, SHL, SHR, ROR, ROL.


As most know, computers only see 1's and 0's. A good way to think of this, is "on" and "off", or "set" and "not set".

So any number, character, be it a byte: 0000:0000 (Hexadecimal 0x:00), a word: 0000:0000:0000:0000 (Hexadecimal 0x:00:00), an dword 0x:00:00:00:00, and a quadword 0x:00:00:00:00:00:00:00:00, is represented in this fashion.

1 = 0000:0001
2 = 0000:0010
4 = 0000:0100
So on and so forth.

The best way to explain this, is division by 2 and multiple of 2.


MOV AL ,  1  ; AL = 1, or 0000:0001
SHL  AL ,  1  ; AL = 2, or 0000:0010
SHR  AL ,  1  ; AL = 1, or 0000:0001

; Note AL is an 8 bit register.

As should be apparent, the 1 moves SHL (Left) and SHR (Right). ROR and ROL behave in the same way, however, with the following differences.


MOV AL ,  1  ; AL = 0000:0001 = 1
SHR AL ,  1  ; AL = 0000:0000 = 0

MOV AL ,  1  ; AL = 0000:0001 = 1
ROR AL ,  1  ; AL = 1000:0000 = 128

Note: In the SHR instruction the 1 was SHifted Right (And there's nowhere for the 1 to shift right to).
In the ROR instruction the 1 was ROtated Right or ROlled Right (So the 1 was ROlled to the other side of the 8 bit register).

The rest of the instructions (I hope I can continue with a decent explanation of as my mind is starting to falter), should be apparent with the following code.


MOV  AL ,  0b101    ; AL = 5 = 0000:0101
AND  AL ,  0b11      ; AL = 1 = 0000:0001
;  AND means that all 1's are kept, so
;  0101
;& 0011    Note: Only the final 1's line up. The rest do not.
;  0001
MOV AL ,  0b101    ; AL = 5
 OR AL ,  0b11        ; AL = 7 = 0000:0111
; Or means "if" a 1 exists in any place, any operand, it stays put.
MOV AL , 0b101 ; AL = 5
XOR AL , 0b011 ; AL = 6
; XOR basically is like saying "opposing bits shall always be 1, and all like bits shall be 0".
; 1 xor 1 = 0
; 0 xor 0 = 0
; 1 xor 0 = 0 xor 1 = 1

MOV AL , 5  ; AL = 0000:0101
NOT AL        ; AL = 1111:1010
; Basically, NOT reverses the bits.  If 1, then 0, or if "on" then "off".

All of this may seem confusing, but in programming, this is a very necessary part of that experience. Many algorithms can be broken down to using just a few if not all of these instructions. Even high level programming can benefit with their use.

(My brain has faltered, and can't concentrate any more. If anyone has any questions, it'd sure help with focusing my thoughts, but there's too few of us oddballs out there who'd like to know more, :rolleyes:)

All times are GMT -5. The time now is 04:49 PM.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2021, vBulletin Solutions, Inc.
Shoutbox provided by vBShout v6.2.1 (Lite) - vBulletin Mods & Addons Copyright © 2021 DragonByte Technologies Ltd.
vBulletin Security provided by vBSecurity v2.2.2 (Pro) - vBulletin Mods & Addons Copyright © 2021 DragonByte Technologies Ltd.

Content Relevant URLs by vBSEO 3.3.2