练习自修改内存复制例程,6502 ASM

时间:2016-02-10 13:36:08

标签: assembly 6502

以下是我在Commodore 64上进行内存复制的自修改例程。

我在表格中写了char codesnumber of repeats,并使用此例程填充了screen_ram。

我正在寻找优化建议。在这种情况下,我的首要任务是记忆。

memCopy:    
  sourceAddress=*+1 ; mark self modifying addrres
fetchNewData:
  lda data_table    ; read char value into A
  ldx data_table+1  ; read repeat value into x
  inc sourceAddress     
  inc sourceAddress 

  cpx #00           ; if X=0 
  beq end           ; finish copying

  destination=*+1
- sta SCREEN_RAM
  inc destination
  dex
  bne -

  jmp fetchNewData

end:
  rts   

; data format:  <char>,<number of repeats>,[<char>,<number of repeats>,...],00,00

data_table: 
!by 01,03,02,02,......,00,00

3 个答案:

答案 0 :(得分:3)

JMP fetchNewData - &gt; BEQ fetchNewData。在INC sourceAddress后移动BEQ endCPX #0LDX之后)无需移动package info.demo.demo.activity; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.text.format.DateUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import info.ballerina.ballerina.R; import info.ballerina.ballerina.helper.ParseUtils; import info.ballerina.ballerina.helper.PrefManager; import info.ballerina.ballerina.model.Message; public class MainActivity extends AppCompatActivity { private static String TAG = MainActivity.class.getSimpleName(); // private Toolbar mToolbar; private ListView listView; private List<Message> listMessages = new ArrayList<>(); private MessageAdapter adapter; private PrefManager pref; WebView webview; ProgressBar loadingProgressBar, loadingTitle; ImageView logo; int first = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // getWindow().requestFeature(Window.FEATURE_PROGRESS); //getWindow().getDecorView().setSystemUiVisibility(0x10); setContentView(R.layout.activity_main); loadingProgressBar = (ProgressBar) findViewById(R.id.progressbar_Horizontal); logo = (ImageView) findViewById(R.id.imglogo); webview = (WebView) findViewById(R.id.webview); webview.getSettings().setJavaScriptEnabled(true); final Activity activity = this; webview.setWebChromeClient(new WebChromeClient() { public void onProgressChanged(WebView view, int progress) { // Activities and WebViews measure progress with different scales. // The progress meter will automatically disappear when we reach 100% loadingProgressBar.setProgress(progress); //loadingTitle.setProgress(newProgress); // hide the progress bar if the loading is complete if (progress == 100) { loadingProgressBar.setVisibility(View.GONE); logo.setVisibility(ImageView.GONE); webview.setVisibility(WebView.VISIBLE); first = 1; } else { loadingProgressBar.setVisibility(View.VISIBLE); if (first == 0) { webview.setVisibility(WebView.GONE); logo.setVisibility(ImageView.VISIBLE); } else if (first == 1) { logo.setVisibility(ImageView.GONE); } } } }); webview.setWebViewClient(new WebViewClient() { public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_SHORT).show(); } }); webview.loadUrl("http://www.demo.com/"); listView = (ListView) findViewById(R.id.list_view); /* mToolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(mToolbar); getSupportActionBar().setDisplayShowHomeEnabled(true);*/ adapter = new MessageAdapter(this); pref = new PrefManager(getApplicationContext()); listView.setAdapter(adapter); Intent intent = getIntent(); String email = pref.getEmail(); if (email != null) { ParseUtils.subscribeWithEmail(pref.getEmail()); } else { Log.e(TAG, "Email is null. Not subscribing to parse!"); } } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); String message = intent.getStringExtra("message"); Message m = new Message(message, System.currentTimeMillis()); listMessages.add(0, m); adapter.notifyDataSetChanged(); } private class MessageAdapter extends BaseAdapter { LayoutInflater inflater; public MessageAdapter(Activity activity) { inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { return listMessages.size(); } @Override public Object getItem(int position) { return listMessages.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; if (view == null) { view = inflater.inflate(R.layout.list_row, null); } TextView txtMessage = (TextView) view.findViewById(R.id.message); TextView txtTimestamp = (TextView) view.findViewById(R.id.timestamp); Message message = listMessages.get(position); txtMessage.setText(message.getMessage()); CharSequence ago = DateUtils.getRelativeTimeSpanString(message.getTimestamp(), System.currentTimeMillis(), 0L, DateUtils.FORMAT_ABBREV_ALL); txtTimestamp.setText(String.valueOf(ago)); return view; } } @Override public void onBackPressed() { if (webview.canGoBack()) { webview.goBack(); } else { super.onBackPressed(); } } } 。少3个字节。

答案 1 :(得分:3)

正确增加指令的地址应该是这样的:

address=*+1
    lda self_modifying_address
    inc address+0
    bne *+5
    inc address+1
因此,可能忽略了自修改代码的所有内存节省。

我建议采用另一种方法,包括仅在需要绝对值的情况下自修改指令地址,并在指令中存储内存变量。

.loop
fetch_ptr=*+1
    ldx #0
    lda filler_bytes,x ;have two tables, first contains only filler bytes,
    ldy repeat_bytes,x ;second only repeat counts
    beq .exit
    inc fetch_ptr      ;this way you save 1 increment

fill_ptr=*+1
    ldx #0
.fill
    sta SCREEN_RAM,x
    inx
    bne +
    inc .fill+2 ;only self-modify high byte of address in the instruction
+   dey
    bne .fill

    stx fill_ptr

    jmp .loop
.exit
    rts


filler_bytes !byte 1,2,3,4,5,4,3,2,1
repeat_bytes !byte 4,4,5,5,6,6,5,5,4,0

答案 2 :(得分:1)

除了i486的建议,如果data_table限制为128个值(包括终止0,0),那么你可以通过避免自我来节省几个字节(和很多周期)修改LDA并改为使用Y寄存器。

我已经展示了以下所有内容。您还可以通过将INY值放入两个单独的表中来保存另一个字节(删除一个data_table)。

或者您可以使用Y来索引SCREEN_RAM,但我不是C64家伙...

  ldy #0
fetchNewData:
  lda data_table,y  ; read char value into A
  iny               ; [could remove if two tables]
  ldx data_table,y  ; read repeat value into x
  beq end           ; finish copying [x=0]
  iny

  destination=*+1
- sta SCREEN_RAM
  inc destination
  dex
  bne -
  beq fetchNewData

end:
  rts   

; data format:  <char>,<number of repeats>,[<char>,<number of repeats>,...],00,00

data_table: 
!by 01,03,02,02,......,00,00