LINUX.ORG.RU

и опять asm + dos


0

0

Как это работает с [si] и всякими ds:bx?

Например у меня стоит задача превратить число в текст:

; in: ax - number
; out: ds:bx - text
; cx - number of digits
itoa proc
...
itoa endp

Именно с такой спецификацией.

Допустим number of digits я уже правильно посчитал.

Я делаю так:

itoa proc
	push ax
	push bx
	push dx	
	
	mov si, cx ; index to the end
	mov bx, 10 ; dividing by 0
	mov [si], 0 ; 0 to the end
	dec si

get_digit:
	xor dx, dx ; zero dx before dividing
	div bx	
	add dl, 48 ; digit -> char
	dec si 
	mov [si], dl 
	or ax, ax
	jnz get_digit

	pop dx
	pop bx
	pop ax

	ret
itoa endp

И что теперь мне с этим [si] делать? Где вообще это [si]?

Если я буду иметь char[] в виде:

.data
text1 db 512 dup(?)

То если:
mov ax, @data
mov ds, ax
mov dx, offset text1

То это я могу понять. Теперь под ds:dx мой text1. Но какое это имеет 
отношение к [si]? Как [si] относится к text1 и к ds:dx? Как все это в памяти соотносится?

И как скопировать содержимое [si] в text1? А как в ds:bx?

И верно ли что я делаю так:

mov si, cx ; index to the end

где cx = number of digits?

Или я вообще где-то совсем не прав?

Ах... [si] это ds:si... Вопрос снят.

Вместо mov si, cx надо:

add bx, cx
mov si, bx

Если text1 в ds:bx.

И потом соответственно можно через это самое [si] все что угодно сделать.

dissident ★★
() автор топика
Ответ на: комментарий от dissident

Только не очень понятно, зачем понадобилось перекидывать указатель в si, если можно было дальше действовать с bx, а свой делитель 10 загнать в освободившийся cx. Значение si, кстати, в функции не сохраняется.

madcore ★★★★★
()

Финогенов. Самоучитель по системным функциям MS-DOS. Настольная книга вирусописателя. Теперь таких не пишут. Некоторое время назад вышло 2-е издание, так что найти не проблема.

Macil ★★★★★
()

Dos'а и какого-нибуть tasm'а под рукой нет, но как-то так:

; in: ax - number
; out: ds:bx - text
; cx - number of digits
itoa proc
	push dx	
	push si
	
	mov si, bx
	add si, cx	; index to the end
	inc si	        ; for final zero

; вместо этих трёх команд должно скатить: lea si, [bx + cx + 1]

	mov [si], 0	; 0 to the end
	mov bx, 10	; dividing by 10

get_digit:
	xor dx, dx	; zero dx before dividing
	div bx	
	add dl, '0'	; digit -> char
	dec si 
	mov [si], dl 
	or ax, ax
	jnz get_digit

	pop si
	pop dx
	ret
itoa endp

mv ★★★★★
()
Ответ на: комментарий от redgremlin

> ЕТМ, кто то еще под 16бит на асме кодит, писец какой-то...

Очень хорошо развивает воображение. К тому же, я не представляю хорошего программиста без знания ассемблера: как он будет искать баги, если даже отладчиком толком пользоваться не сможет?

mv ★★★★★
()

Да, кстати... Если на входе уже известно число разрядов (в cx), то цикл правильнее делать с декрементом cx

mv ★★★★★
()
Ответ на: комментарий от mv

>К тому же, я не представляю хорошего программиста без знания ассемблера

Асм асмом, но 16бит реалмоде? Встретит он какой нить cmova eax, ebx и? Понятно, что надо с чего то начинать, но я бы асм-вставки предпочел досу.

redgremlin ★★★★★
()

>Например у меня стоит задача превратить число в текст:

>; in: ax - number >; out: ds:bx - text >; cx - number of digits >itoa proc >... >itoa endp

>Именно с такой спецификацией.

Тут ничего не сказано про знак числа которое надо преобразовать - если число отрицательное то вообще все неправильно.

anonymous
()
Ответ на: комментарий от redgremlin

Человек - явно студент, и у него идёт курс вроде "Программная и аппаратная организация ЭВМ"

mv ★★★★★
()
Ответ на: комментарий от mv

>; in: ax - number
>; out: ds:bx - text
>; cx - number of digits
>itoa proc
> push dx
> push si

> mov si, bx
> add si, cx ; index to the end
> inc si ; for final zero

Ерундой занимаетесь - в сх должно быть количество байт в целевой строке которое до преобразования еще не известно - его получить надо а вы прибавляете его здесь и получите ерунду потому что вообще не известно что содержит сх в этом месте.

anonymous
()
Ответ на: комментарий от mv

>; вместо этих трёх команд должно скатить: lea si, [bx + cx + 1]

Назовите метод адресации на 8086 с использованием регистра сх ? Чему студентов учите :) Это не будет работать на 8086. Расширенная адресация появилась гораздо позже.

anonymous
()
Ответ на: комментарий от mv

>Про 8086 only в условии ничего сказано :)

А упомянутого формата команды нет ни на каком процессоре :)

KRoN73 ★★★★★
()

itoa proc
push ax
push bx
push dx
push di
push si

mov di,bx
mov bx,10

cmp ax,0
jge positive

neg ax
mov [byte di],'-'
inc di

positive:
xor cx,cx
push_digit:
xor dx,dx
div bx
or dl,'0'
push dx
inc cx

or ax, ax
jnz get_digit

mov si,cx
cld

pop_digit:
pop ax
stosb
loop pop_digit

mov cx,si

pop si
pop di
pop dx
pop bx
pop ax

ret
itoa endp

Вот мой ответ :) Процедура учитывает знак,не добавляет 0 в конце, потому что в сх известна длина строки и вызывающий код может вставить туда по желанию '$' или 0

anonymous
()
Ответ на: комментарий от anonymous

itoa proc
push ax
push bx
push dx
push di
push si

mov di,bx
mov bx,10

cmp ax,0
jge positive

neg ax
mov [byte di],'-'
inc di

positive:
xor cx,cx
push_digit:
xor dx,dx
div bx
or dl,'0'
push dx
inc cx

or ax, ax
jnz push_digit

mov si,cx
cld

pop_digit:
pop ax
stosb
loop pop_digit

mov cx,si

pop si
pop di
pop dx
pop bx
pop ax

ret
itoa endp

Описку нашел jnz push_digit :)

anonymous
()
Ответ на: комментарий от anonymous

itoa proc
	push ax ; сохраняем
	push bx ; используемые
	push dx ; в
	push di ; процедуре
	push si ; регистры

	mov di,bx ; настраиваем текущий указатель (di) на начало строки
	mov bx,10 ; основание системы исчисления (делитель) в bx

	cmp ax,0 ; число на входе >= 0 ?
	jge positive ; да - нормальное продолжение

	neg ax ; нед - инвертируем его
	mov [byte di],'-' ; добавляем минус в начало строки
	inc di ; корректируем текущий указатель на строку

positive:
	xor cx,cx ; сброс счетчика символов
push_digit:
	xor dx,dx ; обнуляем остаток от деления
	div bx ; ax/bx частное->ax остаток->dx
	or dl,'0' ; преобразуем остаток в знак ascii
	push dx ; сохраняем знак в стеке
	inc cx ; увеличиваем счетчик символов

	or ax, ax ; повторить для следующего знака
	jnz push_digit ; пока не дошли до начала числа

	mov si,cx ; сохраняем счетчик символов
	cld ; автоувеличение регистров di,si в строковых операциях
	
pop_digit:
	pop ax ; достаем знак из стека - первый лежит последним
	stosb ; al -> [ds:di], di=di+1
	loop pop_digit ; сх=сх-1, cx=o ? если нет-следующая итерация

	mov cx,si ; восстанавливаем количество символов в строке

	pop si ; восстанавливаем
	pop di ; измененные 
	pop dx ; в 
	pop bx ; процедуре
	pop ax ; регистры
	
	ret
itoa endp

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.