Страница 1 из 1

Перевод с Ассемблера на С

Добавлено: Вт ноя 09, 2010 11:26:02
Slavast
Всем добрый день!
Помогите плиз перевести код программы с Ассемблера на С.
Огромный поклон.


.include "m16def.inc"
.device ATMEGA16


;--задаем имена регистрам------------------
.def temp = r16 ;рабочая переменная


; ---------------Проинициализировали указатель стека------

ldi r16,high(RAMEND) ; Начало
out SPH,r16 ; основной программы
ldi r16,low(RAMEND)
out SPL,r16

;--прерывания------------------------------
rjmp RESET ;Reset Handle
break
reti; jmp EXT_INT0 ; IRQ0 Handler
break
reti; jmp EXT_INT1 ; IRQ1 Handler
break
reti; jmp TIM2_COMP ; Timer2 Compare Handler
break

;reti; jmp TIM2_OVF ; Timer2 Overflow Handler
;break
;reti; jmp TIM1_CAPT ; Timer1 Capture Handler
;break
rjmp TIM1_COMPA
break
break; Timer1 CompareA Handler
break
break
ret; jmp TIM1_COMPB ; Timer1 CompareB Handler
break
break
reti; jmp TIM1_OVF ; Timer1 Overflow Handler
break
reti; jmp TIM0_OVF ; Timer0 Overflow Handler
break
reti; jmp SPI_STC ; SPI Transfer Complete Handler
break
reti; jmp USART_RXC ; USART RX Complete Handler
break
reti; jmp USART_UDRE ; UDR Empty Handler
break
reti; jmp USART_TXC ; USART TX Complete Handler
break
reti; jmp ADC ; ADC Conversion Complete Handler
break
reti; jmp EE_RDY ; EEPROM Ready Handler
break
reti; jmp ANA_COMP ; Analog Comparator Handler
break
reti; jmp TWSI ; Two-wire Serial Interface Handler
break
reti; jmp EXT_INT2 ; IRQ2 Handler
break
reti; jmp TIM0_COMP ; Timer0 Compare Handler
break
reti; jmp SPM_RDY ; Store Program Memory Ready Handler
break


RESET:
;------ Инициализация портов --------

ldi r17, 0x00
out PINA, r17 ; деактивируем Pull-up резисторы

ldi r17, 0x00
out DDRA, r17 ; порт на вывод



sei ;разрешаем прерывания



;------ Инициализация таймера --------


ldi r16, 0x10
out TIMSK, r16 ; разрешение прерывания по совпадению TCNT с OCR


ldi r22, 0x00
out OCR1AH, r22 ;
ldi r22, 0xАА
out OCR1AL, r22 ; устанавливаем предел счета 255




;------------- Тело ----------------------------

ldi r20, 0xAA ; загрузка 10101010 на вывод в PORTA
ldi r21, 0xFF ; слагаемое для Суммы по модулю 2

ldi r16, 0x00
out TCCR1A, r16 ; очистка TCCR1A
ldi r16, 0x0A ; запуск Таймера
out TCCR1B, r16 ; ставим предделитель в CLK/1024



Cycle: ; основной пустой цикл
out PORTA, r20
jmp Cycle


;------- Прерывание --------------



TIM1_COMPA:
nop
push R16 ;
in R16,SREG ; процедура прерывания
push R16 ;
eor r20, r21 ; Изменение 10101010 на 01010101
out PORTA, r20
jmp ttt ; выйти из прерывания

pop R16 ;Востанавливаем регистры
out SREG,R16
pop R16
nop

reti

Re: Перевод с Ассемблера на С

Добавлено: Вт ноя 09, 2010 11:37:28
ARV
в вашей программе есть несуразности и явные ошибки. но код, похоже, сводится примерно к следующему (WinAVR):

Код: Выделить всё

#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER1_COMPA_vect){
   PORTA ^= 0xFF;
}

int main(void){
   DDRA = 0xFF;
   PORTA = 0b01010101;
   OCR1A = 0x00AA;
   TCCR1B = 0x0A; // ох, и не люблю я такие присваивания...
   TIMSK = _BV(OCIE1A);
   sei();
   while(1);
}

Re: Перевод с Ассемблера на С

Добавлено: Вт ноя 09, 2010 11:52:10
Slavast
Это и всё?????????
Вот так вот коротко?
И без описаний всех этих векторов прерываний?

Re: Перевод с Ассемблера на С

Добавлено: Ср ноя 10, 2010 21:10:01
YS
Да, так коротко. :) Всю заботу о прерываниях, стеке и т.д. компилятор берет на себя. :) Равно как и еще кучу других вещей. Беда только в том, что делает он это не всегда эффективно. Хотя, справедливости ради стоит сказать, что нынешние компиляторы действительно хороши.

Re: Перевод с Ассемблера на С

Добавлено: Вт ноя 30, 2010 00:26:38
Lana
Всем доброго времени суток.
Помогите пожалуйста перевести код с Ассемблера на С. Программа работы с клавиатурой, написана для 8051.
Заранее огромное спасибо)

---------------------------------------------------
; Подпрограммы для работы с клавиатурой
; ---------------------------------------------------

INKEY_MASK EQU 70h; маска, в которой входы = 1

; подпрограмма ожидания нажатия какой-нибудь кнопки
WaitForKeyPress:
push ACC;
mov P1, #INKEY_MASK; направления портов согласно маске

WaitForKeyPress1:
mov ACC, P1;
anl ACC, #INKEY_MASK; реализация маски
xrl ACC, #INKEY_MASK; "перевернуть" значения в маске
jz WaitForKeyPress1; не нажато ничего?

acall Wait; пауза. от дребезга

mov ACC, P1;
anl ACC, #INKEY_MASK; аналогичные действия
xrl ACC, #INKEY_MASK;
jz WaitForKeyPress1; а сейчас нажато?

pop ACC;
ret; теперь точно что-то нажато

; подпрограмма ожидания отпускания клавиши
; аналогична предыдущей за исключением
; типа перехода
;
; объединение усложняет код
WaitForKeyRelease:
push ACC;
mov P1, #INKEY_MASK;

WaitForKeyRelease1:
mov ACC, P1;
anl ACC, #INKEY_MASK;
xrl ACC, #INKEY_MASK;
jnz WaitForKeyRelease1;

acall Wait;

mov ACC, P1;
anl ACC, #INKEY_MASK;
xrl ACC, #INKEY_MASK;
jnz WaitForKeyRelease1;

pop ACC;
ret; все кнопы отпущены


; подпрограмма определения кода нажатой клавиши "бегущий ноль"
; возвращает (1..12) - код, или 0 - если не нажато ничего
; в аккумулятор
;
RunningZero:
push 02h; итерационная переменная
push 03h; буфер кода
push 04h; бегущий ноль

mov r2, #0Ch;
!clr 03h; буфер пуст пока
mov r4, #0EFh; 0b1110.1111 - (optional)

RunningZeroLoop:
mov ACC, r4;
rr A; в какую сторону бежать (optional)
mov r4, ACC;

mov P1, r4; пуск "ноля" в клавиатуру
nop;
jb P1.6, NextOne1; поочередная проверка по столбцам
mov 03h, 02h; сохранение кода
NextOne1:
dec r2; итерационная переменная - 1
jb P1.5, NextOne2; далее аналогичные действия
mov 03h, 02h;
NextOne2:
dec r2;
jb P1.4, NextOne3;
mov 03h, 02h;
NextOne3:
djnz r2, RunningZeroLoop; хватит?

mov ACC, r3; да, сохр. в аккумулятор

pop 04h;
pop 03h;
pop 02h;
ret;

; подпрограмма проверки АСС[в 1..9, 11] ?
IsDigit:
jz IsDigitNO; NULL - железно неправильный код
cjne A, #0Bh, IsDigitX;
sjmp IsDigitOK; нолик
IsDigitX:; не нолик
cjne A, #9, IsDigitX1;
sjmp IsDigitOK; девять
IsDigitX1:
jc IsDigitOK; девять > кода - это хорошо
IsDigitNO:
mov ACC, #00h; вернуть - нет
sjmp IsDigitRet;
IsDigitOK:
mov ACC, #0FFh; вернуть - да
sjmp IsDigitRet;

IsDigitRet:
ret;

; подпрограмма печати десятичной цифры на дисплейчике
; в @ACC число для преобразования и печати
; ++ нормализует код нуля!
echo:
cjne A, #0Bh, echo1; код нуля
clr C;
subb A, #0Bh; да, "нормализовать"
echo1:
push ACC;
add A, #30h; подготовка в соотв. с ASCII
acall DataWR;
pop ACC; вернуть преобразованный код
ret;

; подпрограмма ввода числа: @ACC - кол-во цифр считать
; результат вернет в @ACC
;
; wait for keypress\ scan keyboard \ print it\ wait for lift
; конечные автоматы внутри
ScanF:
push 02h; состояние автомата
push 03h; временный результат
push 04h; количество ост. цифр для ввода

mov 02h, #00h;
mov 03h, #00h;
mov r4, ACC; теперь аккумулятор свободен
; для общего назначения
jnz ScanFRoute;
mov r2, #02h; ничего вв не надо, лишь * нажать

ScanFRoute:

mov ACC, 02h;
jz ScanFStateS; #00h
dec ACC;
jz ScanFStateA; #01h
dec ACC;
jz ScanFStateB; #02h
jmp ScanFStateF; above #02h;

; --- только цифру можно нажать ---
ScanFStateS:

acall WaitForKeyPress; void
acall RunningZero; ->ACC
push ACC;
acall IsDigit; <-ACC

jz ScanFStateS2; не цифра
sjmp ScanFStateS1;

ScanFStateS1:
pop ACC; цифра
acall echo; отобразить

mov r3, ACC; сохр. результат
mov 02h, #01h; следующее состояние
dec r4; осталось на одну меньше цифр

sjmp ScanFStateS3;
ScanFStateS2:
pop ACC; неправильный ввод
sjmp ScanFStateS3; проигнорировать

ScanFStateS3:
acall WaitForKeyRelease;
ajmp ScanFRoute;

; --- надо цифру или подтверждение ввода (*) ---
ScanFStateA:
mov ACC, r4;
jnz ScanFStateA1; а цифры то еще нужны?
mov 02h, #02h; нет, хватит
sjmp ScanFStateA4;

ScanFStateA1:
acall WaitForKeyPress; void
acall RunningZero; ->ACC
push ACC;
acall IsDigit; <-ACC
jz ScanFStateA3; неправильный для состояния код
sjmp ScanFStateA2;
ajmp ScanFRoute;

ScanFStateA2:; цифра нажата
pop ACC; вот ее код
acall echo;

; "зарядка" новой цифры в результат
push ACC; пусть тут полежит код нажатой клавиши
mov ACC, r3; временный результат
mov B, #0Ah;
mul AB; умножим на 10d
mov r3, ACC; сохраним обратно
pop ACC;
add A, r3; и добавим 1 "свежую" цифру
mov r3, A; теперь результат переформировани

dec r4; на 1 цифру осталось ввести меньше
sjmp ScanFStateA4;

ScanFStateA3:; * или # нажато
pop ACC;
clr C;
subb A, #0Ah;
jnz ScanFStateA4; не *, надо переввести
mov r2, #03h; ура, подтверждение ввода

ScanFStateA4:; завершение ввода
acall WaitForKeyRelease;
ajmp ScanFRoute;
; --- ожидание только * ---
ScanFStateB:
acall WaitForKeyPress; void
acall RunningZero; ->ACC
clr C;
subb A, #0Ah; проверить, * ли?
jnz ScanFStateB1; не, повторить
mov r2, #03h; двигаем к выходу
ScanFStateB1:
acall WaitForKeyRelease;
ajmp ScanFRoute;

; --- вернуть значение числа ---
ScanFStateF:
mov ACC, r3;

pop 04h;
pop 03h;
pop 02h;
ret;