flat assembler
Message board for the users of flat assembler.

Index > Main > local var value out of range

Author
Thread Post new topic Reply to topic
newtrix



Joined: 23 Mar 2022
Posts: 2
newtrix 23 Mar 2022, 20:40
Hello, I'm using Linux and going through a course that uses FASM. I'm attempting to write a simple itoa, but I'm having trouble. I have a separate itoa.inc file and, embarrassingly, I can't figure out how to use a local variable. I have:

Code:
itoa:
    .itoa_idx db ?
    mov [.itoa_idx], '0123456789ABCDEF'
    ...
    


I've also tried defining it outside of the label explicitly, then using it later. This approach yields a value out of range error.
Post 23 Mar 2022, 20:40
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20537
Location: In your JS exploiting you and your system
revolution 23 Mar 2022, 20:52
In x86 code you can't store more than 4 bytes of immediate data into memory with a single instruction.

Your constant '0123456789ABCDEF' is 16 bytes. And your storage space .itoa_idx is one byte.

Something like this maybe:
Code:
    .itoa_idx rb 16 ; reserve 16 bytes
;...
    mov dword[.itoa_idx + 0], '0123'
    mov dword[.itoa_idx + 4], '4567'
    mov dword[.itoa_idx + 8], '89AB'
    mov dword[.itoa_idx +12], 'CDEF'    
You can also store the data directly if the variable .itoa_idx is in an initialised section:
Code:
 .itoa_idx db '0123456789ABCDEF'    
Post 23 Mar 2022, 20:52
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1072
Location: Russia
macomics 23 Mar 2022, 21:16
newtrix wrote:
Code:
itoa:
    .itoa_idx db ?
    mov [.itoa_idx], '0123456789ABCDEF'
    ...    
In this form, the variable will become part of the command and the code will be erroneous.

You can allocate a local variable for a function in the stack:
Code:
itoa:
    label .itoa_idx byte at rbp-16
    push rbp
    mov rbp, rsp
    sub rsp, 16
    mov [.itoa_idx + 0], '0';'0123456789ABCDEF'
    mov [.itoa_idx + 1], '1'
    mov [.itoa_idx + 2], '2'
    mov [.itoa_idx + 3], '3'
    mov [.itoa_idx + 4], '4'
    mov [.itoa_idx + 5], '5'
    mov [.itoa_idx + 6], '6'
    mov [.itoa_idx + 7], '7'
    mov [.itoa_idx + 8], '8'
    mov [.itoa_idx + 9], '9'
    mov [.itoa_idx + 10], 'A'
    mov [.itoa_idx + 11], 'B'
    mov [.itoa_idx + 12], 'C'
    mov [.itoa_idx + 13], 'D'
    mov [.itoa_idx + 14], 'E'
    mov [.itoa_idx + 15], 'F'
;OR
    mov dword [.itoa_idx + 0], '0123';'0123456789ABCDEF'
    mov dword [.itoa_idx + 4], '4567'
    mov dword [.itoa_idx + 8], '89AB'
    mov dword [.itoa_idx + 12], 'CDEF'
    ...

;CLEAR
    mov rsp, rbp
    pop rbp
    ret    

Or define it in the data section as global:
Code:
itoa:
...
segment readwble writeable
itoa.itoa_idx  db '0123456789ABCDEF'    

revolution wrote:
Code:
.itoa_idx db '0123456789ABCDEF'    
Such a declaration in the data section will create the required label only if there is an "itoa" label before this section that doesn't start with a dot ('.').
And if you use 32-bit code, then you can do without an indexing table at all:
Code:
itoa:cmp al, 10
    cmc
    adc al, '0'
    daa ; Invalid, in 64-bit code
...    


Last edited by macomics on 23 Mar 2022, 21:36; edited 2 times in total
Post 23 Mar 2022, 21:16
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20537
Location: In your JS exploiting you and your system
revolution 23 Mar 2022, 21:31
There is also a three instruction conversion.
Code:
        cmp     al,10
        sbb     al,0x69
        das    
It isn't readable or flexible. More of a curiosity than being really needed. And if you want lower case hex letters then it needs further processing.
Post 23 Mar 2022, 21:31
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1072
Location: Russia
macomics 23 Mar 2022, 21:40
revolution wrote:
There is also a three instruction conversion.
Code:
        cmp     al,10
        sbb     al,0x69
        das    
It isn't readable or flexible. More of a curiosity than being really needed. And if you want lower case hex letters then it needs further processing.
Only this will not work in 64-bit code. But I like my version more, even though it is 1 byte longer.

I do not know why lowercase characters may be needed instead of numbers. Only with uppercase numbers look better.
Post 23 Mar 2022, 21:40
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20537
Location: In your JS exploiting you and your system
revolution 23 Mar 2022, 22:05
I don't like either of them. The three or four instruction converters are terrible actually, IMO.

But they are "cool tricks", so they do have some value I guess. Razz

Way back in the good-old-days when saving a few bytes of RAM was vital, and clock counts could be computed by sight, these codes could have been life savers. Now I have GiBs of RAM and clock counts are buried sixteen dimensions deep and impossible to visualise unless you are an advanced level hyper-god. Laughing
Post 23 Mar 2022, 22:05
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1072
Location: Russia
macomics 23 Mar 2022, 22:14
revolution wrote:
I don't like either of them. The three or four instruction converters are terrible actually, IMO.

But they are "cool tricks", so they do have some value I guess. Razz

Way back in the good-old-days when saving a few bytes of RAM was vital, and clock counts could be computed by sight, these codes could have been life savers. Now I have GiBs of RAM and clock counts are buried sixteen dimensions deep and impossible to visualise unless you are an advanced level hyper-god. Laughing
Support. Only it is faster to write 3-4 commands, rather than a construction with an index table. It is only because of the greater evidence of constant values that I like my version.
Post 23 Mar 2022, 22:14
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4182
Location: vpcmpistri
bitRAKE 24 Mar 2022, 00:55
Post 24 Mar 2022, 00:55
View user's profile Send private message Visit poster's website Reply with quote
newtrix



Joined: 23 Mar 2022
Posts: 2
newtrix 24 Mar 2022, 23:08
Wow, thanks for all the replies to this. The very first solution(s) worked just fine, and I have a working itoa now. Is it appropriate for me to put it in code blocks and ask for critiques/suggestions?

EDIT: I'll look at those neat tricks you guys showed for conversion. At a glance I presume they also only work for base 10? Mine is meant to work for any base < 17.
Post 24 Mar 2022, 23:08
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20537
Location: In your JS exploiting you and your system
revolution 25 Mar 2022, 00:48
newtrix wrote:
EDIT: I'll look at those neat tricks you guys showed for conversion. At a glance I presume they also only work for base 10?
They are only valid for bases <= 16 with upper-case letters. And only valid for execution modes of 32 bits or less, not for 64 bit mode.

So as mentioned, not very flexible. And not universal.
Post 25 Mar 2022, 00:48
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1072
Location: Russia
macomics 25 Mar 2022, 07:43
how it works
Code:
cmp     al, 10  ; al=  0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |10 |11 |12 |13 |14 |15 |16 |...
cmc             ; al=  0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |10 |11 |12 |13 |14 |15 |16 |...
adc     al, '0' ; al= '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' ';' '<' '=' '>' '?' '@' 'A' ...
daa             ; al= '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' 'A' 'B' 'C' 'D' 'E' 'F' 'A' ...    

Code:
cmp     al, 10  ; al=  0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |10 |11 |12 |13 |14 |15 |16 |...
sbb     al, 105 ; al= x96|x97|x98|x99|x9A|x9B|x9C|x9D|x9E|x9F|xA1|xA2|xA3|xA4|xA5|xA6|xA7|...
das             ; al= '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' 'A' 'B' 'C' 'D' 'E' 'F' 'A' ...    

To translate a byte consisting of 2 characters, this is even still relevant in 32-bit programs. The advantages can also include the fact that the translation of the sign is carried out in a limited space. There is no need to release an entire 32/64-bit register to access the table.

To translate a 16/32/64-bit value, you should use a different algorithm.
Although it is still possible to discuss about the 16-bit value, but for 32-bit and 64-bit values, you can write more efficient variants of parallel translation of all 4-bit-groups in a number.
One of the options for translating the 64-bit value was given by bitRAKE. But for a 32-bit program, it is not obvious that the processor has the SSE3 extension.
Post 25 Mar 2022, 07:43
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.