GNU Asembler - konwersja liczby z dziesietnego na szesnastkowy

0

Witajcie,
Mam problem z wykonaniem zadania. Zadanie to polega na konwersji liczby z systemu dziesiętnego na system szesnastkowy a następnie wypisanie wartości. (Liczba początkowa jest z góry zadeklarowana).
Wszystko działa dla liczby max 8 bitowej (mniejszej niz 255) gdy naprzykład podam liczbe 280 przy próbie ponownej kompilacji występuje następujący błąd:
Warning: value 0x118 truncated to 0x18
Rozumiem,że błąd pochodził ze złej deklaracji typu danych (zamiast word wykorzystałem byte - za mała pojemnosc)
Przy próbie zmiany z byte na word program wypisuje totalne głupoty - naprzykład dla wartości 280 wypisał "0x18".
Składnia GNU Asembler - jestem totalnie zielony i jest to moja pierwsza styczność z tym językiem programowania dlatego proszee o wyrozumiałość i pomoc ! :D
Poniżej załączam kod programu - czy ktoś jest w stanie podrzucić jakieś pomysły/rozwiązanie ? Heeelp ! :D

.globl _start

.data
	
var:	.byte	 240		# jesli zamienie na .word 280 - wypisuje glupoty

outstr:	.ascii	"value = 0xhl\n"
.equ	strlen, . - outstr
 
.text
	
_start:

#pass only the necessary arguments

	mov	var,%al
	mov	$outstr+10,%rdi

#invoke conversion

	call	convert_byte

#print the result

	mov	$1,%eax
	mov	$1,%edi
	mov	$outstr,%rsi
	mov	$17,%edx
	syscall

#and exit

	mov	$60,%eax
	xor	%edi,%edi
	syscall


#convert byte to a string (hex)

convert_byte:

	mov	%al,%bl

	and	$0x0F,%al
	call	convert_nibble

	shl	$8,%ax

	mov	%bl,%al
	shr	$4,%al
	call	convert_nibble

	mov	%ax,(%edi)

	ret

convert_nibble:
	cmp	$10,%al
	jc	below10
	add	$55,%al
	ret
below10:
	add	$48,%al
	ret
2

Nie no cały ten kod trzeba poprawić. Masz np. mov var,%al a al to 8 bitów. Masz też mov %al,%bl i znów używasz rejestrów 8 bitowych. Siłą rzeczy nawet jak zmienisz tą początkową deklaracje na worda to potem wpiszesz sobie kawałek tej liczby do al i potem to konwertujesz. Co zresztą widać w twoim błędzie, podałeś liczbę 0x0118 czy dwa bajty 01 18, a po przypisaniu mov var,%al do al poszedł tylko ten niski bajt więc 0x18

0

Bardzo dziękuje za odpowiedź ! :D
No więc po wielu próbach zamiany rejestrów wykombinowałem tak skoro long to liczba 32bit to wykorzystałem rejestry 32bitowe:

globl _start
 
.data
   
var:   .long	3735927486  
 
outstr:	.ascii	"value = 0x0000000000000000\n"
.equ    strlen, . - outstr
 
.text
   
_start:
 
 
    mov var,%eax
    mov $outstr+10,%rdi #Tutaj tej linii kompletnie nie rozumiem co oznacza +10?
 
 
    call    convert_byte
 
 
    mov $1,%eax
    mov $1,%edi
    mov $outstr,%rsi
    mov $17,%edx
    syscall
 
 
    mov $60,%eax
    xor %edi,%edi
    syscall
 
 
#convert byte to a string (hex)
 
convert_byte:
 
    mov %eax,%ebx
 
    and $0x0F,%eax
    call    convert_nibble
 
    shl $8,%rax #w poprzednim kodzie nigdzie nie był wykorzystany rejestr ax ale był to rejestr dwukrotnie większy więc analogicznie zamieniłem go na rax
 
    mov %ebx,%eax
    shr $4,%eax  #co tutaj sie dzieje ?
    call    convert_nibble
 
    mov %ax,(%edi)
 
    ret
 
convert_nibble:
    cmp $10,%eax
    jc  below10
    add $55,%eax
    ret
below10:
    add $48,%al
    ret

Co do pierwszego komentarza Wiem tylko tyle,że w poprzednim przypadku działało to tak: do rejestru przeznaczenia zostaje załadowany wskaźnik wskazujący na 10 #miejsce w outstr – tam będzie załadowany wynik funkcji convert_byte #czyli przekonwertowana liczba.
Co do drugiego i trzeciego komentarza to wiem tylko tyle,że przesuwa wszystkie bity z %ax o 8 w lewo, daje miejsce na drugi znak
Niestety program dalej nie działa - kompiluje się ale - wypisuje jedynie wartość: 0x00000000
Co dalej robie źle :/ ? Czy ktoś/Pan jest mi w stanie wyjaśnić co

0

Na początku nauki warto korzystać ze składni intela, a nie AT&T,
dodając na początku kodu:

.intel_syntax

Aby przekonwertować liczbę wykonujesz:

 call    convert_byte

Program, w pierwszej wersji robił to co ma robić, konwertował bajt.
Aby dokonać konwersji większej liczby, będzie potrzebne więcej pracy.
Nie kopiuj bezmyślnie kodu, bo tylko wydłużasz swoją pracę.

SHL - przesunięcie bitów w lewo
SHR - przesunięcie bitów w prawo

0

Zacznij od zastanowienia sie jak ten kod w ogóle działa a nie jak to przerobić. Czemu w ogóle reprezentacja hex? ;) Popatrz na to co się dzieje jak masz liczby reprezentowane jako hexy, jak to odpowiada bajtom! Cały trik polega na tym że jeden bajt odpowiada jednej "cyfrze" szesnastkowej. Liczba 0xABCD ma cyfry A, B, C, D i składa się też, na poziomie pamięci, z takich właśnie bajtów! Więc konkwersje 0xABCD na liczbę szesnastkową można by spokojnie zrobić po jednym bajcie. Mogłes nie ruszać tej funkcji convert byte którą miałeś, a zamiast tego wywołać tą funkcje w pętli, dla każdego bajtu twojej wejściowej liczby. Jedyne o czym trzeba pamiętać to endianness -> czy mniej znaczące bajty są z przodu czy z tyłu liczby tzn czy masz w pamieci ABCD czy DCBA.

1 użytkowników online, w tym zalogowanych: 0, gości: 1