программа для tasm
Составить программу, которая последовательно (в цикле) вводит по одному целому числу и находит количество положительных чисел, которые не делятся на 10. Признак окончания работы программы – ввод нуля.
без понятия, как её делать?
как ввести ещё примерно знаю...а дальше..
записывать каждое число в отдельный реестр и сравнивать каждый с каждым? :confused:
введёное число сравнить с нулём . если равно нулю , то выводим результат , а если нет , то проверяем знак и не делимость на 10 . если результат проверки положителен , та счётчик увеличивем .
ничего запоминать не надо .
ты же не забыл,что число из аски вида нужно в хекс еще переводить,нет?
mov ax,num
cmp ax,0
ja bolshe_nulya
;меньше нуля
bolshe_nulya:
div 0Ah
cmp ah,0
jz delitsya
;не делится на ноль
delitsya:
;не делится на ноль
…
НА НОЛЬ!!!Ухаха!:D
Спасибо,повеселил:)
А проверку на знак можно сделать с помощью JS/JNS.Тогда будет как-то так
JNS Unsigned
<Здесь код для числа со знаком.Но его вроде по условию не предполагается.Но если будет…>
Jmp BlockEdge
Unsigned:
<Ну тут сам Бог велел>
BlockEdge:
Спасибо,повеселил:)
тяжелый день.ну все же поняли,что я имел в виду
привычка.таки я не указал какого типа в ax заносится значение,чтобы ah обнулить,очевидно же
Тут уже всё указано.Команда Mov работает только с операндами одного размера
спасибо конечно, но я не понял(
ух ты,не знал.
;не делится на 10
.data
a dw ? ;место в памяти для введенного числа
str1 db 'Количество $' ;сообщение, предваряющее вывод количеству
.stack 32h
.code
.startup
extrn read:near, writer:near
call read ;вводим число, оно попадает в ах
cmp ax,0
jz vveden_nol
mov ax,num
cmp ax,0
ja bolshe_nulya
;меньше нуля
bolshe_nulya:
div 0Ah
cmp ah,0
jz delitsya
;не делится на ноль
delitsya:
vveden_nol:
mov ah, 9 ;выводим строку-сообщение
lea dx, str1
int 21h
mov ax,bx ;восстанавливаем в ах значение суммы
call writer ;и выводим количество чисел на экран
.exit 0
end
div 0Ah нужно заменить на
mov cx,0Ah
div cx
и,если число попадает в а,то его нужно переместить в ax,перед cmp ax,0
кстати,что за read\write?
Как же вы раньше работали,не зная?Ассемблер нормально переваривал загон в двухбайтовый регистр 4х байтов?:D
Ну вообще есть определённый метод сопряжения,допустим,регистра(AX,например) и двойного слова,но всё равно операция будет осуществляться только с одним размером.Пример
Честно пися́,я подумал,что имелся в виду как раз прикол:)
.data
a dw ? ;место в памяти для введенного числа
str1 db 'Количество $' ;сообщение, предваряющее вывод количеству
.stack 32h
.code
.startup
extrn read:near, writer:near
call read ;вводим число, оно попадает в ах
mov ax,a
cmp ax,0
jz vveden_nol
cmp ax,0
ja bolshe_nulya
;меньше нуля
bolshe_nulya:
mov cx,0Ah
div cx
cmp ah,0
jz delitsya
;не делится на 10
delitsya:
xor ax,ax
inc ax
vveden_nol:
mov ah, 9 ;выводим строку-сообщение
lea dx, str1
int 21h
mov ax,bx ;восстанавливаем в ах значение количества
call writer ;и выводим количество чисел на экран
.exit 0
end
исправил. теперь ошибок нет. Но оно не работает ни разу. И цикл ещё надо поставить....чтоб оно работало, пока не введён 0.
Но оно и без цикла не работает(((
кстати,что за read\write?
Для ввода целого числа будем пользоваться процедурой READ, после вызова которой введенное число попадает в регистр АХ. Для вывода на экран целого числа, находящегося в регистре АХ, будем использовать вызов процедуры WRITER.
Данные процедуры вызываются с помощью команды САLL. Эта команда передает управление процедуре, сохранив перед этим в стеке смещение к точке возврата. Процедура выполняется до тех пор, пока среди ее команд не встретится команда возврата RET, которая достает из стека адрес возврата и передает управление команде, следующей за командой САLL.
Поскольку процедуры READ и WRITER являются внешними для программы, которая будет их использовать, необходимо с помощью директивы EXTRN информировать компилятор о том, какие именно имена являются внешними, то есть определенными во внешнем модуле, скомпилированным самостоятельно и независимо от основного программного модуля. В нашем случае данная директива может быть использована следующим образом:
extrn read:near, writer:near
очень просто - никак.с самого начало у меня из-за какой-то ошибки не заработала такая конструкция, и я всегда использовал mov с косвенной адресацией,а там и размер операнда передавал через ptr.
хорошо написанно,из какой книги?и страницу,если можно.также интересно,почему вы для вывода строки используете прерывание,а для вывода числа - функцию?
она уже частично есть.
delitsya:
xor ax,ax
inc ax
на
jmp main
delitsya:
xor ax,ax
inc ax
jmp main
ну а main пихнуть чуть выше call read
.STACK 64
data segment
sum db 0
in_buff db 5,?,5 dup(?)
mess db "Answ:"
out_buff db 5 dup(?)
shift db 0dh,0ah,'$'
num dw 0
data ends
code segment
assume cs:code, ds:data
START:
mov ax,data
mov ds,ax
L1: mov ax,0a00h
lea dx,in_buff
int 21h
mov ax,0900h
lea dx,shift
int 21h
cmp [in_buff+2],'-'
jz L1
cmp [in_buff+2],'0'
jz ext
mov si,offset in_buff
call AsciiToDword
mov ax,num
mov bx,0ah
div bl
cmp ah,0
jz L2
jmp L1
L2: add sum,1
jmp L1
ext: lea si,out_buff
call DwordToAscii
mov ax,0900h
lea dx,mess
int 21h
mov ax,0a00h
lea dx,in_buff
int 21h
mov ax, 4c00h
int 21h
AsciiToDword proc
.386
xor ax,ax
mov bx,1
mov cl,[si+1]
add si,cx
inc si
L: mov al,[si]
and al,0Fh
mul bx
add num,ax
imul bx,10
dec si
loop L
ret
AsciiToDword endp
DwordToAscii proc
.486
xor dx,dx
movzx ax,sum
mov bx,10000
mov cx,5
L3: div bx
add ax,30h
mov [si],al
inc si
push dx
xchg ax,bx
mov bx,10
xor dx,dx
div bx
xchg bx,ax
pop ax
loop L3
ret
DwordToAscii endp
CODE ends
end START
не сочтите за наглость, но не могли бы вы комментарии по вставлять?)
.STACK 64
data segment
sum db 0 ;число положительных,кратных 10
in_buff db 5,?,5 dup(?) ;буффер вводимого числа
mess db "Answ:"
out_buff db 5 dup(?) ;буфер выводимого числа
shift db 0dh,0ah,'$'
num dw 0
data ends
code segment
assume cs:code, ds:data
START:
mov ax,data
mov ds,ax
L1: mov ax,0a00h ;чтение числа
lea dx,in_buff
int 21h
mov ax,0900h
lea dx,shift
int 21h
cmp [in_buff+2],'-' ;если отрицательное
jz L1
cmp [in_buff+2],'0' ;если введен ноль
jz ext
mov si,offset in_buff
call AsciiToDword ;если ни то,ни то - переводим строку в число
mov ax,num
mov bx,0ah
div bl ;делим на 10
cmp ah,0 ;в ah остаток от деления
jz L2 ;если остаток = 0
jmp L1
L2: add sum,1
jmp L1
ext: lea si,out_buff
call DwordToAscii ;число в строку
mov ax,0900h ;вывод на экран
lea dx,mess
int 21h
mov ax,0a00h
lea dx,in_buff
int 21h
mov ax, 4c00h
int 21h
AsciiToDword proc
.386
xor ax,ax
mov bx,1
mov cl,[si+1]
add si,cx
inc si
L: mov al,[si]
and al,0Fh
mul bx
add num,ax
imul bx,10
dec si
loop L
ret
AsciiToDword endp
DwordToAscii proc
.486
xor dx,dx
movzx ax,sum
mov bx,10000
mov cx,5
L3: div bx
add ax,30h
mov [si],al
inc si
push dx
xchg ax,bx
mov bx,10
xor dx,dx
div bx
xchg bx,ax
pop ax
loop L3
ret
DwordToAscii endp
CODE ends
end START
алгоритмы перевода строки в число и числа в строку просты:
1)от каждого символа отнимает 30h,получаем разряд числа,умножаем его на число,эквивалентное разряду,суммируем.
2)число делится сначало на самый старший эвивалент разряда,получаем разряд,добавляем 30h и приводим к аски символу,записываем в строку,повторяем циклично.эквивалент разряда с каждой итерацией уменьшается