以下是我在Commodore 64上进行内存复制的自修改例程。
我在表格中写了char codes
和number 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
答案 0 :(得分:3)
JMP fetchNewData
- &gt; BEQ fetchNewData
。在INC sourceAddress
后移动BEQ end
,CPX #0
(LDX
之后)无需移动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