07-15-18, 10:15 PM
|
#11
|
Junior Member
Join Date: Sep 2010
Location: Kansas
Posts: 85
My Mood:
|
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.
Code:
; #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
itobf_ret:
MOV BYTE [RDI], 0
RET
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, )
#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.
Code:
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.
Code:
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.
|
|
|
07-17-18, 08:50 PM
|
#12
|
Member
Join Date: Oct 2014
Posts: 625
|
I like it lol
And I hope you feel better soon!
__________________
Be who you are and say what you feel, because in the end those who matter don't mind and those who mind don't matter. - Dr. Seuss
|
|
|
07-18-18, 10:08 PM
|
#13
|
Junior Member
Join Date: Sep 2010
Location: Kansas
Posts: 85
My Mood:
|
Oh-kay! I revamped my itob routine, it's a bit longer than the old one, but it's still pretty quick.
Code:
; itob( char * source, int A, int len)
itob:
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.
itob_ret:
MOV WORD [RDI], AX
RET
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.
Basically,
Code:
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, . Meh, the pain caused me too much duress and I really really had a hell of a time thinking on this.
|
|
|
Sponsored Links
|
Advertisement
|
|
07-20-18, 04:13 AM
|
#14
|
Junior Member
Join Date: Sep 2010
Location: Kansas
Posts: 85
My Mood:
|
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...
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".
Code:
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.
Code:
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...
|
|
|
07-26-18, 02:08 AM
|
#15
|
Junior Member
Join Date: Sep 2010
Location: Kansas
Posts: 85
My Mood:
|
Mental note to self: The following code is perfectly fine...(I asked someone in another forum and they concurred).
Code:
MOV reg , [reg]
AND reg , [reg]
; etc
|
|
|
08-02-18, 11:30 PM
|
#16
|
Junior Member
Join Date: Sep 2010
Location: Kansas
Posts: 85
My Mood:
|
Holy halibuts I'm having such trouble concentrating...
Anyhoo, I got the first macros at least finished.
Code:
; 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
%endrep
MOV %1, RSP
%endmacro
%macro resetFrom 1-*
MOV RSP, %1
%rep %0-1
%rotate -1
POP %1
%endrep
%endmacro
; mpush mpop Multi Push and Pop
;
; Keep order for quick copy/paste in vim.
%macro mpush 1-*
%rep %0
PUSH %1
%rotate 1
%endrep
%endmacro
%macro mpop 1-*
%rep %0
%rotate -1
POP %1
%endrep
%endmacro
This way, I can use the following code (and quick copy/paste within vim).
Code:
backupTo RBP, reg1, reg2, reg3, ...
; ... Do stuff here
resetFrom RBP, reg1, reg2, reg3, ...
; And
mpush reg1, reg2, ...
; ... Do stuff here
mpop reg1, reg2, ...
|
|
|
10-06-18, 09:20 PM
|
#17
|
Junior Member
Join Date: Sep 2010
Location: Kansas
Posts: 85
My Mood:
|
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.
Makefile
Note: Need to research .PHONY in a Makefile.
Code:
ASMSRC=$(wildcard *.asm)
ASMOBJ=$(patsubst %.asm,%.o,$(ASMSRC))
ASSDBG= -g dwarf2
ASS=yasm
ASSFLAGS= -f elf64 $(ASSDBG) $(USEWITHC) -D HEX_DELEM="'-'" -D _USE_BIN_SUFFIX_
CSRC=conv.c
PRGNAM=convtest
CC=gcc
CFLAGS= -g -Wall
all: $(ASMOBJ) ccode
%.o: %.asm
$(ASS) $(ASSFLAGS) $< -o $@
ccode:
$(CC) $(CFLAGS) $(CSRC) $(ASMOBJ) -o $(PRGNAM)
clean:
rm $(ASMOBJ) $(PRGNAM)
itobs.asm
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.
Code:
; 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.
%ifdef BINARY_DELEM
%ifnstr BINARY_DELEM
%define BINARY_DELEM ':'
%endif
%endif
section .text
global itobs
;
;
; itobs( src , C , len )
; itobs( RDI , RSI , RDX )
;
; len == 0, return a single bit.
;
; Registers used: CL
;
itobs:
AND DL , 111111b ; Ensure <= 64 bits are read.
INC DL
MOV CL , DL ; Only CL can be used by ROR.
ROR RSI , CL
%ifdef _USE_BIN_PREFIX_
MOV AX , '0b'
MOV WORD [RDI], AX
ADD RDI , 2
%endif
itobs_loop:
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.
%ifdef BINARY_DELEM
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.
%else
JNZ itobs_loop
%endif
itobs_exit:
%ifdef _USE_BIN_SUFFIX_
MOV AX , 0x0062
MOV WORD [RDI], AX
%else
MOV BYTE [RDI], 0 ; Write null char.
%endif
RET
itoxs.asm
Code:
; 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 ':'
%endif
%endif
section .text
global itoxs
; itoxs( char *src, number, length )
;
; itoxs( RDI, RSI, RDX )
itoxs:
AND DL , 1111b ; < 64 bits.
MOV CL , DL ; CL can only be used with RO#
SHL CL , 2
ROR RSI , CL
%ifdef _USE_HEX_PREFIX_
MOV AX , '0x'
MOV WORD [RDI], AX
ADD RDI , 2
%endif
itoxs_loop:
MOV AL , SIL
AND AL , 1111b
CMP AL , 10
JL itoxs_less
ADD AL , 7
itoxs_less:
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
MOV BYTE [RDI], HEX_DELEM
INC RDI
JMP itoxs_loop
%else
JNS itoxs_loop
%endif
itoxs_exit:
%ifdef _USE_HEX_SUFFIX_
MOV AX, 0x0068
MOV WORD [RDI], AX
%else
MOV BYTE [RDI], 0
%endif
RET
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.
|
|
|
10-14-18, 09:53 PM
|
#18
|
Junior Member
Join Date: Sep 2010
Location: Kansas
Posts: 85
My Mood:
|
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".
|
|
|
11-11-18, 12:47 AM
|
#19
|
Junior Member
Join Date: Sep 2010
Location: Kansas
Posts: 85
My Mood:
|
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.
Prerequisite:
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.
SHL, SHR
The best way to explain this, is division by 2 and multiple of 2.
Code:
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.
Code:
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.
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, )
|
|
|
|
|