Сборка: проблемы с увеличением места в памяти

Я только начинаю сборку 6502, и пытаюсь разобраться в основах. Я использую эмулятор JavaScript на своем телефоне для сборки кода. Я пытаюсь заставить его увеличить p (моя ячейка памяти) и сохранить A в обоих адресах (в качестве прелюдии к циклу позже). Но при запуске он сохраняет только A до 0205 долларов, а не 0206 долларов (именно это я пытаюсь заставить его делать). Любая помощь приветствуется.

LDA #$01
define p $0205
STA p
INC p
STA p

person Jaws88    schedule 25.12.2018    source источник
comment
Вы увеличили только p, что равно $0205. Вы никогда не получали доступ к $0206.   -  person Raymond Chen    schedule 26.12.2018
comment
Что делает INC p, увеличивает память на 0205? Он не может увеличивать p, так как это всего лишь идея, а не значение в памяти или регистре.   -  person ctrl-alt-delor    schedule 26.12.2018
comment
Это неправильное высокоуровневое мышление. Любые рекомендации о том, как увеличить сам адрес памяти?   -  person Jaws88    schedule 26.12.2018
comment
@RaymondChen, можешь объяснить?   -  person ctrl-alt-delor    schedule 26.12.2018
comment
Инструкция Inc увеличивает байт. Вы увеличили p, что равно $0205. Вы ничего не сделали с $0206.   -  person Raymond Chen    schedule 26.12.2018
comment
6502 не так легко работает с указателями, как это делают более современные ISA с достаточно широкими регистрами для хранения указателя. См. раздел Почему компиляторы с C на Z80 создают плохой код? для сводки ограничений 8-разрядных процессоров, таких как 6502. I думаю, вы хотите sta p / sta p+1, потому что p - это только константа времени сборки.   -  person Peter Cordes    schedule 26.12.2018
comment
Еще один ужасный процессор - интер x86. У него регистры большего размера (как у z80, но со всеми регистрами специального назначения вы тратите большую часть своих инструкций, просто перемещая данные из регистра в регистр. По крайней мере, 6502 красив и прост).   -  person ctrl-alt-delor    schedule 26.12.2018
comment
@ctrl-alt-delor: возможно, вы не смотрели на x86 с 8086 года. Начиная с 386 добавлены режимы ортогональной адресации (где любой регистр может быть базовым или индексным), movsx и movzx для расширения знака / нуля в регистры, отличные от AX, и умножать на/из любого регистра (например, imul ebp, dword [rdi+rax*4], 12345), регистры x86 являются плоскими/ортогональными для большинства целей. Инструкция loop устарела, поэтому осталось только несколько вещей с фиксированным регистром: счетчики сдвига в CL (исправлено BMI2 shlx/shrx) и целочисленное деление. Вывод компилятора x86-64 не заполнен mov reg,reg из-за специальных регистров.   -  person Peter Cordes    schedule 03.01.2019
comment
@PeterCordes Я не смотрел много кода x86, но это был пост 586. Я уверен, что когда вы сравниваете современный x86 с 8086, он выглядит так хорошо, но я не сравниваю его с этим. Я сравниваю его с процессором с хорошей архитектурой, таким как arm, 68000, sparc, Alpha, Mips, …   -  person ctrl-alt-delor    schedule 03.01.2019
comment
@ ctrl-alt-delor: Я тоже. x86-64 как цель компилятора (ортогональные регистры и т. д.) не сильно отличается от других современных ISA. ARM может быть более эффективным, чем большинство RISC, из-за своего бочкообразного переключателя, позволяющего выполнять сдвиги как часть других инструкций, но x86-64 может сворачивать загрузки в операнды памяти для других insns. Я не говорю, что ARM плохая или что x86-64 лучше ISA, но ваше заявление о том, что вы тратите много инструкций на перемещение данных из-за специальных регистров, является полной чушью, если не считать код, полный переменных. -count сдвигается с несколькими разными счетами.   -  person Peter Cordes    schedule 03.01.2019
comment
x86 имеет значительное количество mov инструкций, но это потому, что целочисленные инструкции имеют 2 операнда с деструктивным dst/src. Не из-за специальных регистров. lea - это обходной путь для сдвига и добавления. ISA с тремя операндами, скорее всего, была бы более эффективной, но с проблемами x86 можно справиться до тех пор, пока ее не заменит что-то лучшее. У него довольно хороший набор инструкций SIMD, особенно с AVX512, заполняющим многие пробелы. У ARM нет эффективной векторной > целочисленной маски (pmovmskb), поэтому сложно писать циклы поиска ARM SIMD, но в остальном NEON подходит.   -  person Peter Cordes    schedule 03.01.2019


Ответы (2)


Код, который вы написали, делает не то, что вы думаете. p — это просто определенное имя для числа $205. По сути, ваша программа

LDA #$01
; define p $0205
STA $0205
INC $0205
STA $0205

Инструкция INC увеличивает содержимое ячейки $0205, но затем она немедленно перезаписывается второй STA.

Есть несколько способов сделать то, что вы хотите. Во-первых, если это всегда место p и следующее, в зависимости от вашего ассемблера, вы должны написать

LDA #$01
define p $0205
STA p
STA p+1

Это поместит 1 в $0205 и $0206. В качестве альтернативы, если вы хотите выполнять приращение во время выполнения, используйте индексный регистр, из которых есть два X и Y.

LDA #$01
define p $0205
LDY #0
STA p,Y
INY 
STA p,Y

Это не лучше, чем предыдущее, но его можно использовать в цикле.

define p $0205
define count 10

    LDA #$01
    LDY #count
loop:
    DEY        ; Decrement Y by 1 setting the zero flag if zero
    STA p,Y    ; Store the result in p + Y (flags are unaffected)
    BNE loop   ; Go round the loop if the zero flag is not set

Приведенный выше код заполнит ячейки от p до p + 9 константой 1. Обратите внимание, что он делает это, перемещаясь вниз по памяти.

Если p неизвестно до времени выполнения, вы можете сделать то же самое, но используя косвенный адрес нулевой страницы.

define p $0205
define count 10
define ptr $50 ; A random zero page location

    LDA #$01
    LDY #count

; First load the address in the zero page location

    LDA <p     ; < is a common notation for the low byte of a 16 bit number ($05 in this case)
    STA ptr
    LDA >p     ; and > is for the high byte ($02 in this case)
    STA ptr+1

; Now a similar loop to before

loop:
    DEY        ; Decrement Y by 1 setting the zero flag if zero
    STA (ptr),Y; Store the result in p + Y (flags are unaffected)
    BNE loop   ; Go round the loop if the zero flag is not set
person JeremyP    schedule 02.01.2019

Я думаю, вы поместили адрес (0205) в индексный регистр (я думаю, что у 6502 их 2). Сохраните A по адресу, на который указывает индексный регистр, увеличьте индексный регистр и сохраните A по адресу, на который указывает индексный регистр.

person ctrl-alt-delor    schedule 25.12.2018
comment
Я думаю, что его индексные регистры имеют ширину всего 8 бит. Он может эффективно индексировать относительно фиксированной базы для статического адреса, для 8-битного индекса, но у него нет полных регистров указателя. Почему компиляторы с C на Z80 создают плохой код? описывает некоторые ограничения (упоминает 6502, а также z80/8080) . - person Peter Cordes; 26.12.2018