GitHub for WindowsでGitHub以外のリポジトリを扱う方法
ファイルデータ読み込み時のEOF判定(型に注意)
C言語でバイナリファイのダンププログラムを書いていた際に、
EOFの判定部分でハマったのでメモ。
バイナリファイルを最後まで読み込むときにはEOF(-1)を
読み込みの終了条件にすることが多い。
ファイルから1byteずつ読み込んでダンプしたい場合に
読み込みデータをsigned char型 or unsigned char型変数に格納すると、
ファイルの途中で0xff(-1)があった場合に
そこでファイルの読み込みが終了してしまう。
(0xffとEOFが区別できない)
なので、読み込みデータはint型変数に読み込む必要がある。
そうするとEOFの際は0xffffffff、ファイル内の0xffは0x000000ffが
変数に格納されるので、両者を区別できる。
以下がサンプルプログラム。
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { FILE *fp = NULL; // while文の比較でEOF(-1)とファイル内の0xffとを区別するため、charでなくintで宣言 // これにより、ファイル内の0xffは0x000000ff, EOFは0xffffffffとなるので比較段階で区別できる int mask = 0; int c = 0; mask = (unsigned char)strtol(argv[2], NULL, 16); if ( ( fp = fopen(argv[1], "r") ) == NULL ) { printf("file open error!\n"); return 1; } // cに格納される値を上記コメントの要領で判定 while( ( c = fgetc(fp) ) != EOF ) { c ^= (unsigned char)mask; printf("%x", (unsigned char)c); } printf("\n"); fclose(fp); return 0; }
write()実行後にexit()しないとコアダンプする(解決)
昨日の記事、
write()実行後にexit()しないとコアダンプする - kurokuronatto's blog
の疑問が解決したのでメモ。
C言語のプログラムだと、最初にCRT(C Runtime)からmain関数が呼ばれる。
その後main関数終了後のreturnでCRTに処理が戻り、
CRTの中でexit()が呼ばれてプログラムが終了する。
しかしアセンブリ言語の場合にはCRTがないので、自分でexit()を読んでやらないと
プログラムが終了せず、テキスト領域の外にあるコードを実行しようとする。
そこでセグメンテーション違反が発生する。
なるほど、実行領域の違反ってことでセグメエラーになったのね。。
勉強になった。
CRTは、確かCのプログラムでスタティックリンクされるライブラリだったかな?
よく分からないから、また調べてみよ。
write()実行後にexit()しないとコアダンプする
低レイヤーに興味があって、現在x86アセンブリ言語を勉強中。
環境はUbuntu13.10, アセンブラにはnasmを使用。
例えば次のように書くと、標準出力に"HelloWorld"が出力される。
BITS 32 section .data msg db "HelloWorld", 0x0a section .text global _start _start: ;SYSCALL: write(1, msg, 14) mov eax,4 mov ebx,4 mov ecx,msg mov edx,11 int 0x80 ;SYSCALL: exit(0) mov eax,1 mov ebx,0 int 0x80
実行結果: HelloWorld
しかし、上のソースコードでexit(0)の部分のみを削除するとコアダンプする。
実行結果: HelloWorld Segmentation fault(コアダンプ)
この理由がよく分からないんだけど・・・。
普通にC言語で書いた場合、最後にexit 0;をつけてもつけなくても
ちゃんと動作する。
アセンブリ言語の場合は何か違うのかなー?
Cの場合はコンパイラが自動でexit(0)を挿入してくれるとか?
そもそも何でセグメ違反になるんだろう。