yamamotoさんはじめまして。>加算した下位2byteのチェックサム値を算出する下位2byteだけを使うならunsigned shortで桁あふれが起きても問題ないと思います。どうせ上位は捨ててしまうのですから。ちゃんと4バイトで計算して下位2バイトを残すのであればunsigned short sum(2バイト)ではなくunsigned long sum(4バイト)で試してみてはいかがでしょう。
yamamotoさんこんなんでいかがでしょうか?ごめんなさい最初の投稿は早とちりでした。問題は、コンパイラオプションでラージモデル(コード1Mバイト、データ1Mバイト)を選択したにも関わらず、ポインタ変数(4バイト変数)が64K空間しか扱えていないということですね。(少なくともアセンブラコード上はadr++を2バイト変数として扱っている模様)対策でポインタをやめて、キャストでメモリアクセスに変えてみました。#define ROM_START 0x00000#define ROM_END 0x1FFFFmain(){ unsigned long adr; unsigned long rom_end; unsigned short sum; adr = ROM_START; rom_end = ROM_END; sum = 0; while(adr <= rom_end) { sum += (unsigned short)(*(unsigned char *)adr); adr ++; };}
分かりました!コンパイラの仕様でどんなに頑張ってもポインタのインクリメントやアドレス比較は下位2バイトしかしてくれないそうです。help見ると>- farポインタの加減算は,下位2バイトで行い,上位は変化しません。ですって。ポインタを使っての64K超えは無理なので、「回答番号 2」のコードでやるしかなさそうです。
頭の体操でROMのチェックサム計算アセンブラ版を作ってみました。16bitマイコンで16bitを超える計算させると、頭がパンクしますね。ちなみに、シミュレータでブレークポイントを使うとROMのチェックサムが狂うようです。OCDエミュレータならソフトブレークを設定した命令コードが書き換わるのは仕方ないですけれども、シミュレータでこの仕打ちにはやられました。【アセンブラソース】ROMSTART EQU 000000HROMEND EQU 01FFFFHORG 0H DW STARTORG 0D8HSTART: CLRW AX MOVW DE,AX; DEにチェックサム MOVW HL,#LOWW ROMSTART MOV B,#LOW (ROMSTART/10000H)LOOPS: MOV A,B MOV ES,A CMP A,#LOW (ROMEND/10000H) BZ $LOOPE ;最終セグメントならLOOPEへLOOP: MOV A,ES:[HL] MOV X,A CLRB A XCHW AX,DE ADDW AX,DE XCHW AX,DE INCW HL CLRW AX CMPW AX,HL BNZ $LOOP MOV A,B INC B CMP A,#LOW (ROMEND/10000H) BC $LOOPS ;LOOPSに無条件ジャンプでも良さそう BR $LOOPOUTLOOPE: MOV A,ES:[HL] MOV X,A CLRB A XCHW AX,DE ADDW AX,DE XCHW AX,DE MOVW AX,#LOWW ROMEND CMPW AX,HL INCW HL BNZ $LOOPELOOPOUT: MOVW AX,DE ;チェックサムをAXにコピー BR $$ ;無限ループで止まるEND