2017-01-19 2 views
0

Итак, я давал проект для записи программы, в которой хранится значение в ячейке памяти, 0x200, тогда программа уменьшает значение и сохраняет его в следующем месте памяти. Я только начал программирование сборки, и я склонен писать его с менталитетом письма с языком высокого уровня. Вот код, который я создал (он выглядит очень много, но это только причина комментариев):AVR сборка, увеличение и уменьшение значений из памяти данных

.cseg 
.org 0x200 ;Trying to get the program to start assemblimg from memory location, 0x200 

.DSEG 
store: .BYTE 1 ;Trying to "create a variable called store to represent memory location, 0x200" 

.CSEG 
    lds r17, store ;loading variable store into registry 17 

.def count = r16 
    ldi count, 0x04 ;the first value, 0x04 assigned to variable, count and stored in registry 16 


lp: 

    sts store, r16 ;stores value in r16, i.e. 0x04, into store which should point to memory location 0x200 

    cpi count, 0x00 ;check if value is zero yet 

    breq done ;if value is zero end program 

    dec count ;decrement the value of count, i.e. 0x04 

    inc r17 ;increment content of r17, which is store which refers to memory locaion, 0x200 

    rjmp lp ;restart loop 


done: jmp done ;end of program 

Я знаю, что это немного неаккуратно причиной замечаний, жаль что Если это помогает это был первый код, который я пытался, но r15 не работает с петлями:

.cseg 
.org 0 

lds r15, 0x200 
lds r17, 0x001 

.def count = r16 
    ldi count, 0x04 


lp: 
    sts r15, r16 
    cpi count, 0x00 
    done 
    dec count 
    ADD r15, r17 
    rjmp lp 

done: jmp done 
+1

Обратите внимание, что ваши директивы '.org' отчасти испорчены - вы, кажется, считаете, что они действительны глобально для каждого сегмента. Это неправда. Вы в настоящее время только ставите код в 200h - .dseg не имеет .org, поэтому ваши данные будут помещены начиная с адреса 0 (если у вас нет сценария компоновщика, который помещает материал в нужные места). AVR основан на * архитектуре Гарварда *, поэтому код и данные имеют два разных адресных пространства. – tofro

+0

@tofro, так как мне обойтись, если dseg начнет сборку с 0x200? –

ответ

0

STS k,Rr: магазины один байт из регистра в пространстве данных. Для частей с SRAM пространство данных состоит из файла регистра, ввода-вывода и внутренней SRAM (и внешней SRAM, если применимо).

ST Z, Rr, ST Z+, Rr, ST -Z, Rr, STD Z+q, Rr: Магазины один байт непрямого с или без смещения из регистра в пространстве данных. Для частей с SRAM пространство данных состоит из файла регистра, ввода-вывода и внутренней SRAM (и внешней SRAM, если применимо).

Вы должны использовать ST инструкции и один из регистров указателей (X, Y и Z) для хранения одного байта из регистра в специальный адрес RAM.

Как это:

.def count = r16 
.equ array_size = 5 

.dseg 
.org 0x200 
array_region: .BYTE array_size 

.cseg 
.org 0 

; Vector Table (Offset 0 -> Rest) 
JMP start 



.org INT_VECTORS_SIZE*2 ; Here is end of vector table 
RJMP start 
.include "m32def.inc" ; We should specify a special AVR for using its definitions 

; Start From Here 
start: 

; Initializing Stack Pointer (to the end of RAM). You must do it for returning from subroutines and Interrupts. 
;LDI  R16,LOW(RAMEND) 
;LDI  R17,HIGH(RAMEND) 
;OUT  SPL,R16 
;OUT  SPH,R17 


LDI XL, LOW(array_region) ; Low byte of X 
LDI XH, HIGH(array_region) ; High byte of X 

LDI count, array_size 

lp: 
ST X+, R16 
DEC count 
BREQ done ; 'DEC' instruction will effect on Z flag. 
RJMP lp 

done: JMP done 

Обратите внимание, что регистры указателя равны R26 к регистрам R31 ([R27: R26] => Х, [R29: R28] => Y, [R31: R30] => Z).

+1

Я действительно смущен. Я понимаю, что 'ST X +, R16' хранит счет от R16 до X, а X + переходит в следующую ячейку памяти данных после каждого цикла, правильно? Но что именно делает ADD R15, R17? И как «R15» связан с X, он появляется только один раз. –

+0

Что касается всего между 'start:' и 'lp:', я думаю, что мне нужно будет купить и прочитать книгу об этом, чтобы понять это. –

+0

@DrewU извините. 'ADD R15, R17' осталось от предыдущего кода! Кроме того, вы совершенно правы в отношении 'ST X +, R16' и' X' –

1

Я не уверен, в чем вопрос, но я постараюсь помочь.

STS k, Rd  ; stores Rd to address k. 

STS известен как адресация Direct Data, которая требует постоянной для хранения данных. Используя STS потребует, чтобы мы жёстко каждый магазин, который не является точно хорошим решением. Что вам нужно - это косвенное обращение к данным, ST.

X, Y и Z - регистры указателей, которые могут использоваться для указания конкретных адресов.

ST Y+, R16 

Приведенный выше код сохранит то, что находится в R16, в адрес Y, а затем увеличит Y на единицу.

В вашем примере вы вызвали .org 0 в .cseg. Что это будет делать, так это сделать начальный адрес (источник) для хранения в 0x00 для памяти программы. Чтобы установить источник в памяти данных на 0x200, вам необходимо вызвать .org 0x200 в .dseg.

Я сделал это из кода, который вы указали, немного изменил его. Он должен работать.

.dseg 
.org 0x200 

Пример:

.dseg    ;Data segment 
.org 0x200   ;Start storing at 0x200 
storage: .byte 1 ;Allocate 1 byte for storage 

.cseg     ;Code segment 
ldi yH, high(storage) ;storage <== Y 
ldi yL, low(storage) 
ldi r16, 0x2B   ;Load r16 with 0x2B 

loop: 
    st Y+, r16  ;Address Y <== r16, increments Y by 1. 
    cpi r16, 0x00 ;Compare r16 to 0. 
    breq end  ;If zero status bit is 1, branch to end. 
    dec r16  ;Otherwise, decrement and loop. 
    rjmp loop 

end:    ;End loop 
    jmp end 

Проверьте AVR Инструкция по монтажу Set. ST позволяет хранить и пред-инкремент/декремент или значения после инкремента/декремента в X, Y или Z. Если вы хотите хранить вещи из регистров в последовательных ячейках памяти данных, используйте:

ST X, Rd 
+0

Эй, мне действительно нужно было изменить код, потому что в нашем проекте было обновление, и это похоже на ваше , за исключением того, что я использовал Z, который ссылался на константу '0x4f', которая затем была загружена в' r16'as за заданные инструкции. Я хотел спросить, предполагая, что у вас есть переменный «результат», который относится к ячейке памяти 0x200 .... как бы вы могли увеличить ее до следующего местоположения в цикле –

+0

imply put, мне пришлось заменить 'Y +', с результатом, который указывает на '0x200', но я не знаю, как его увеличить. –

+0

Это просто синтаксис. 'X',' Y' и 'Z' относятся к соответствующему адресу указателя. Вы не можете заменить это поле постоянным или другим регистром. Так или иначе вам нужно загрузить это число в регистр указателя. Сохраните, а затем увеличьте то, что находится в этом регистре, перед тем, как зациклиться на вашем описании. Если вам нужно больше информации [вот страница руководства] (http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_ST.html) по инструкции ST – Arcaeic

Смежные вопросы