2014년 11월 27일 목요일

Mini vMac

초기 Macintosh에 대한 에뮬레이터로 종종 언급되는 것이 바로 이 Mini vMac이다.

그런데 어찌된 일인지 사용하기가 무지 까다롭다.

정확히 말하자면 내.가. 사용하기에 무지 까다로왔다.

아직까지도 제대로 써 보질 못했으며, 써 보려고 시도한 것도 수차례이며, 같은 삽질이 반복되고 있다는 것은 정말 화가 날 지경이다.

그래서 더 이상은 삽질하지 말자는 의미로 여기에 정리해 두려 한다.



1. Mini vMac
공식적인 홈페이지가 sourceforge에 있었는데 이번에 방문해 보니 다른 곳으로 옮겼다고 한다.
http://www.gryphel.com/c/minivmac/index.html
여기에서 Mini vMac 바이너리를 다운로드 받을 수 있다.

2. ROM
어디에서 구했는지 기억은 나지 않지만, Macintosh Plus용 ROM을 가지고 있으며 여기에 저장해 둔다.
Mac_Plus_ROM.zip
압축을 풀면 vMac.ROM 이름의 파일이 나온다. 이 이름 그대로 사용하면 된다.

3. System 6 OS
위의 Mini vMac 사이트에서 설명한대로라면 Apple 사이트에서 이 오래된 OS의 디스크 이미지를 받을 수 있어야 하는데, 어찌된 일인지 지금은 링크가 사라진 듯 보인다.
그래서 이것도 여기에 보관해 두었다.
SSW_6.0.8_Disk 1 of 2
SSW_6.0.8_Disk 2 of 2

4. Stuff-it Expander
위의 디스크 이미지를 그대로 사용하려고 하면 작동하지 않는다는 것을 알게 된다.
확장자도 .bin이라서 더 이상 뭐가 있겠나 싶었는데, Macintosh에서 사용되는 Stuff-it이라는 압축 프로그램으로 압축이 되어 있으니 이걸 풀어야 한다고 한다.
그런데 이게 뭐 유명하지도 않고 Macintosh에서나 사용되는 프로그램이라 구하기가 녹녹하지는 않아 보인다.
일단은 Linux용의 Stuff-it 압축 프로그램을 찾아냈다.
혹시 모르니 이것도 보관.
Stuffit520.611linux.tar.gz

5. System 6 디스크 이미지 풀어내기
4번의 Stuff-it으로 3번의 System 6 디스크 이미지를 풀면 되지 않는가?
그것만으로는 안되더라는....ㅠㅠ
먼저 디스크 1번의 압축을 풀어보면, *.info, *.rsrc, *.data 세개의 파일이 나온다.
여기에서 *.data 파일을 다시 압축을 풀면 System Startup이라는 파일이 나온다.
이 파일이 1.44MB의 디스크 이미지이고, Mini vMac에서 인식할 수 있는 파일이다.
혹시 모르니 이것도 여기에 보관.
System Startup
디스크 2의 압축을 풀어서 나온 이미지도 여기에 보관.
System Additions

System 6 디스크 압축 풀기

2014년 11월 11일 화요일

Ubuntu 10.04에 Java 설치하기

Ubuntu 10.04의 소프트웨어 센터에는 구글의 크롬도 없고, 오라클의 자바도 없다.
대신 Chromium이라는 크롬 호환 브라우저가 있고, OpenJDK라는 자바 호환 플랫폼이 제공된다.

아마도 Ubuntu의 버전이 오래되다 보니, 캐노니컬에서 정식으로 지원하지 않는 것인지, 혹은 개별 소프트웨어 업체가 워낙에 막강하다보니 굳이 Ubuntu의 소프트웨어 센터에 등록하지 않아도 된다 생각한건지...

하지만 Ubuntu의 소프트웨어 센터가 매우 편리하고, 이것이 아니라도 apt-get으로 간단히 설치가 가능해 진 이 시점에... 개별적 설치는 이래저래 번거로운 문제가 되어 버렸다.

그리고 캐노니컬에서 지원하지 않는 소프트웨어 패키지 가운데에는 설치가 아얘 불가능해 보이는 것들도 종종 마주치게 되고, 설치해도 여러가지로 찜찜한 경우는 더 자주 발생한다.

크롬 브라우저도 Ubuntu 10.04에서는 이런 경우에 속하는 패키지라 Chromium을 사용하고 있는데, 여기에 Java가 필요한 상황에 부딪히게 되었다.

편리한대로 OpenJDK를 설치해 보았는데, 이게 무슨 일인지 Java Application 실행에도 문제가 있고 브라우저에서 Java Applet을 실행하는 데에도 문제가 생겼다. 아니, 문제가 아니라 아얘 설치전과 마찬가지로 작동하지 않는 것...

OpenJDK라서 그런가도 싶고, OpenJDK는 버전 업데이트가 어찌 되는지도 의심스럽고 해서 번거롭지만 Oracle Java를 설치하기로 했다.

다음 사이트에서 Java(JRE)를 다운로드 한다. Ubuntu 10.04의 경우는 Linux 링크를 클릭하면 된다.
http://java.com/ko/download/manual.jsp?locale=ko
Java Download

위의 화면에서 "지침"을 클릭하면 다음과 같은 화면이 나오지만, 링크가 따로 있으니 이걸 클릭.
설치 지침 - Ubuntu용 Java로 이동하자

위의 링크따라 이동하면 처음엔 OpenJDK에 관한 설명이 나오는데, 스크롤해서 내려가면 Oracle Java 부분이 나온다.
Ubuntu용 Java 설치 지침 가운데 Oracle Java

위의 화면에서 "2. How do I install Oracle JRE 7?"을 클릭하면 다음과 같은 화면이 나온다.
JDK 기준으로 설명하지만 JRE도 비슷하다.
Oracle Java 설치 과정

설치 과정

Java(JRE) 설치에 대한 설명 계속. 플러그인 부분은 따르지 말고 다음에 나오는 화면을 따라하자.
Oracle Java 설치 과정(계속)

더 아래로 스크롤하면 JRE에 대한 설명이 따로 나온다.
그리고 여기에 브라우저 plugin 설정하는 방법이 나온다.
파이어폭스와 Chromium 모두 동일하게 다음의 방법으로 설정이 가능하다.
브라우저 플러그인 설정

브라우저 플러그인 설정 과정. 내 경우에는 mkdir과 ln 두가지 명령만으로 끝.
브라우저 플러그인 설정

Chromium에서 Java 설치 확인
Chromium에서 Java 설치 확인

FireFox에서도 Java 설치 확인
FireFox에서 Java 설치 확인


2014년 11월 5일 수요일

Vim 파일 저장 오류 __ 10

최종 오류의 원인으로 등장한 stat() 함수.
하지만 DOSBox에서는 실패한 이 함수의 결과가 시험용을 작성한 코드에서는 성공했다.
어째서 다른 결과가 나온 걸까?

gdb를 이용해서 어셈블리 코드 레벨의 실행 절차마저 세세하게 따져봐야 할 지경에 이르게 되었다.
하지만 Linux gdb에서의 어셈블리 코드의 표기가 MS-Windows 계열에서 사용하는 표기와 너무 달라서 해독이 난감해 하던 터였다.

일단, 지난 번에 만든 stat() 함수를 사용하는 테스트용 C program의 Assembly code를 생성해 보았다.
실행 결과야 이미 알고 있으니 최대한 단순하게 만들어서 Assembly code도 간단하도록 간략화 시켰다.

stat() 테스트 프로그램

gcc에서 -S 옵션을 사용하면 Assembly Code를 출력한다.
gcc -S 옵션
그렇게 만들어진 Assembly Code는...
테스트 프로그램의 Assembly Code
역시나 뭔가 참 어색하다.
상수값에 $를 쓴다거나 레지스터 이름에 %를 붙인다는 걸 알 수 있지만, 오퍼랜드의 순서가 바뀌어 있고, %gs:20 ?? 156(%esp) ??? 이건 대체 뭘까?

Linux용 Assembly 공부를 해야 하나 하고 관련 서적과 자료들을 인터넷에서 검색을 했다.

헌데... CPU는 동일한 인텔 계열인데 굳이 Assembly 공부를 다시 해야 하나?
OS에 관련된 부분을 제외하면 단순히 표기법만 다른 것 아닌가?

그렇다면 gcc에서 Assembly Code를 출력할 때 이 표기법을 바꿀 수 있지 않을까?
전에 어디에선가 본 기억으로는 Assembly Code의 표기법은 AT&T와 Intel의 방식으로 나뉘어져 있으며, AT&T 표기법은 Unix 계열에서, Intel 표기법은 MS-Windows 계열에서 주로 사용한다고 했던 것 같다.
gcc는 MS-Windows용으로도 porting되어 있으니 양쪽 표기법을 모두 지원할 것이라 생각이 들어 gcc 매뉴얼을 다시 살펴 보았다.

그래서 찾아낸 옵션, -masm=intel로 지정해주면 된다.
-masm 옵션
그렇게 만들어진 Assembly Code,
테스트 프로그램의 Assembly Code. Intel 표기법
이제야 조금 익숙해진 모양새.

그렇다면 gdb에서도 Assembly Code룰 보여줄 때 표기법을 바꿀 수 있지 않을까?
그래서 gdb 매뉴얼을 찾아 본 결과,
gdb의 disassemble 옵션

2014년 10월 30일 목요일

버그와 디버깅에 관한 단상

디버깅에 집중하다 보니,
마지막 포스팅에서의 쓸데없는 생각, 자기 자신을 (온전히) 디버깅할 수 있는 프로그램은 없다...

오늘 밤, 아니군 어제 밤, 간만에 산책을 하면서 들어 온 생각
자기 자신을 디버깅 할 수 있는 머신은 과연 불가능한 걸까?
(현재의 프로그램이라는 좁은 제한을 벗어나 모듈화 되고 병렬처리가 가능하고 자기 복제도 가능한 등의 H/W와 S/W를 모두 갖춘 진보된 장치라면 가능하지 않을까?
그리고 이런 기술적인 문제를 넘어서의 고차원적인 문제를 생각해 본 것이다.)

극장판 애니메이션 [공각기동대]의 초반부에 이런 대사가 나온다.
버그가 없는 프로그램도 없지만, 디버깅이 불가능한 프로그램도 없지.




그런가?

2001: A Space Odyssey에는 HAL 9000이라는 인공지능 컴퓨터가 등장한다.
탁월한 능력을 지녔으며 우주선의 모든 것을 관리/제어하는 중요한 역할을 한다.
하지만 지구와의 통신을 위한 위성 안테나 모듈에 문제가 있다는 잘못된(?) 판단을 내린다.
우주선의 항해사들은 HAL 9000에 버그가 발생했다고 생각을 하지만 HAL 9000은 그렇지 않다고 생각한다.

버그를 제거하는 디버깅의 시작은 버그를 인식하는 것이다.
HAL 9000이 제아무리 뛰어나다 해도 그것이 버그라고 인식하지 못한다면 디버깅은 불가능하다.

그렇다면 과연 그것이 버그였을까?
엄격하게 따지자면 그건 버그가 아니었다.
그 문제를 보는 이의 시각에 따라 옳고 그름이 갈리기 때문이다.
그리고 HAL 9000은 나름대로의 이유가 있었기에 안테나 모듈의 문제를 제기했던 것이다.
하지만 항해사들의 입장에서는 문제 없는 모듈에 문제가 있다고 교체를 강요하는 HAL 9000에 큰 버그가 있다고 생각했던 것이다.

만약 모든 입장, 모든 치우침, 모든 편견에서 자유로워진다면 버그라고 인식할 것이 없는 건 아닐까?
결국은 극히 제한된 일부로써의 편향된 입장을 가지게 되면 버그로 인식할 것은 매우 많아지는 것이고, 버그는 그 자체가 문제가 아니라, 그걸 바라보는 이의 편향된 생각이 만들어낸 왜곡된 환상이었던 건 아닐까?


일본의 만화가 우라사와 나오키의 [플루토]를 보면 이런 이야기가 나온다.
최고의 로봇을 만들기 위해 고민을 하던 텐마 박사는 결국 모든 인류의 특성을 한데 모아서 자신의 로봇에게 주입을 했고, 기동을 시켰으나 결국 그 로봇은 깨어나지 못했다고 한다. 모든 인류의 특성을 가진 롯봇은 결국 자신의 주체를 혼동하여 결정하지 못했기 때문이라고...




2014년 10월 29일 수요일

Vim 파일 저장 오류 __ 9

stat() 함수는 왜 실패했을까?
Ubuntu에서 stat() 함수에 애초부터 문제가 있었던 건 아닐까?

간단하게 C program을 만들어서 이를 시험해 보기로 했다.

test.c
stat()의 대상 파일은 DOSBox에서 시험을 했던, 디버그 메시지로 출력된 그 파일을 사용했다.
출력 메시지에 자세한 정보를 넣으려 했더니 이상한 에러가 발생해서, 간단하게 성공 실패만 출력하게 만들었다.

빌드하고 시험해 보니....성공...(허무-_-)
test 결과
그렇다면....Ubuntu에서 stat() 함수는 정상적으로 작동한다고 정정해야 겠다.
그렇다면 DOSBox에서는 왜 실패했던걸까?
인자로 전달된 파일 이름에 무언가 보이지 않는 문제가 있었단 말인가?
그 문제를 확인하려면 실제 인자로 전달되는 메모리를 살펴봐야 하지 않을까 싶다.
그러기 위해서는 DOSBox를 디버깅해봐야 한다는 얘기가 되고...
DOSBox의 자체 디버거로 이것이 가능할까?

=================================================================
잠깐, 앞서 언급했던 이상한 에러에 대해서 살펴보자.


test.c에서 printf()에 변수를 출력하기 위해 포맷문자(%)를 사용하면 문제가 생기는 것이었다.
앞선 소스에서 주석처리를 했던 부분을 다음과 같이 다시 살려놓고 빌드해 보았다.
test.c
컴파일에서는 아무런 문제가 없었지만 링킹 과정에서 문제가 생긴 듯한데, 처음보는 이상한 오류를 내놓았다.
이게 ld의 문제라는 것인지 collect2의 문제라는 것인지도 모호하다.
test.c 빌드 에러
google에 오류 메시지를 그대로 붙여넣고 검색해 보니 꽤 많은 결과들이 검색되기는 하지만 딱히 이 경우에 해당되는 문서는 아직 찾지 못했다.
빌드 에러 검색
문제 하나도 해결 못하고 여기까지 왔는데, 이상한 에러까지 더해지니 머리가 복잡해지려고 한다.
일단은 본래의 문제에만 집중하기로 하고, 이 문제는 잠시 접어두기로 하자.
=================================================================
문제 해결!
아주 간단하면서도 어이 없는 실수에 의한 문제였는데,
실패했을 경우를 위해 추가했던 [extern int errno;]와 관련이 있는 문제였다.
외부에 있다고 지정한 errno를 찾지 못해서 에러가 난 것.
이 문제를 해결하려면 [#include <errno.h>]를 추가해 주면 된다.
창피한 실수이긴 하지만, 이런 경우의 에러 메시지를 내지 못하고 세그멘테이션 폴트가 나온다는 것도 이상하지 않냐고 반문해 보고 싶다.
=================================================================

이제 본류로 다시 돌아와서 디버깅에 대해 생각을 해보자.
하지만 오래 생각할 것도 없이, 이 디버깅은 DOSBox의 내장 디버거로는 불가능한 것이다.
DOSBox의 내장 디버거가 다룰 수 있는 범위는 DOSBox 위에서 돌아가는 프로그램들에 국한이 된 것이고, 이 문제는 DOSBox와 Ubuntu에 걸쳐 있는 문제이므로, 아얘 다른 도메인(?, 세상, 차원)에 속하는 것들인 셈이다.
세상 어떤 프로그램이 자기 자신을 완전히 디버깅 할 수 있단 말인가?
세상 어딴 프로그램이 자신의 기반이 되는 모(母)프로그램을 완전히 디버깅 할 수 있단 말인가?
재미있지 않은가?
따지고 보면 인간도 자기 자신을 완벽히 비판하고 파악하는 것은 불가능하다는 말이 되지 않을까?

간단히 말하면, 그래서 gdb를 써야 한다는 것이다.
지금 빌드해 놓은 DOSBox가 내장 디버거를 활성화 시킨 것이라 gdb에서 DOSBox를 바로 호출하게 되면 gdb와 DOSBox의 내장 디버거가 뒤엉킬것이므로, 먼저 DOSBox를 실행시킨 후에 gdb를 attach하기로 했다.
ps로 알아낸 프로세스 번호는 2400, --pid 옵션으로 gdb에 attach 시킨다.
gdb attach
DOS_SetFileAttr()에 breakpoint를 설정한다.
문제가 되었던 localDrive::GetFileAttr()에 설정할 수도 있겠지만 원하지 않을 경우에도 break가 걸리게 될 것이므로...
set breakpoint
continue로 DOSBox를 실행시키고, vim에서 파일을 불러온 후에 수정하고 저장을 시도한다.
그러면 설정해 두었던 breakpoint에서 멈추게 된다.
이제 문제가 되었던 stat() 지점까지 n(ext)와 s(tep)으로 진행을 한다.
next/step
stat()을 호출하기 직전에 인자로 사용되는 변수 newname의 값이 어떤지 확인해 본다.
gdb의 p(rint)로 문자열을 확인하면 모든 값들이 표시된다고 보면 될 것이다. 출력 불가능한 문자들의 경우에는 "\nnn "으로 표시해 주니까 중간에 이상한 문자가 끼었는지는 금방 알 수 있다.
확인해 보니 변수값에 이상한 문자가 없음을 확인할 수 있다.
next/step/print
자세히 보면 그냥 NEWFILE이 아니라 NEWFILE.~임을 알 수 있다.
지난 번의 DOSBox 디버그 출력에도 있었는지 모르겠지만, vim에서 파일을 저장할 때 원본 파일과 <원본.~>파일 두개를 동시에 저장하려 하는 것으로 보인다.
step
그런데 stat()에서 s(tep)으로 진입을 해 보니, 인자의 값이 newname이 아닌 name의 값으로 표시가 된다.???
계속해서 s(tep)으로 들어가 보지만 더 이상 깊이 들어갈 곳은 없어 보인다.
c(ontinue)로 이어서 진행을 하자 이번에는 원본파일인 NEWFILE로 다시 한 번 break가 걸린다.
next/step again
이전과 같이 n(ext)와 s(tep)으로 stat()까지 진행.
앞선 경우처럼 stat()에 사용된 인자가 바뀌었을까 이상해서 어셈블 코드를 확인해 보기로 했다.

"disassemble /m"으로 소스와 어셈블 코드를 표시해 본다.

일단 어셈블 코드가 좀 낯설다.
일단 대충 살펴보니, stat()을 호출하는 부분이 보이질 않는다.
단지 test %eax, %eax와 jne 0x80decc0
0x80decc0에서 stat()을 호출하는 걸까?
disassemble
0x80decc0는 stat()의 처리가 실패했을 경우에 처리되는 부분이다.
attr에 0을 넣고 디버그 메시지를 출력하는 코드로 이어진다.
그렇다면 stat()을 호출하는 곳은 어디에 있단 말인가?
앞의 어셈블 코드를 다시 살펴보니 stat()을 전후로 디스어셈블 되지 않은 번지들이 있음을 알게 되었다. 즉, 0x80dec66에서 0x80dec85로 약 0x1F(31) 바이트 정도가 보이질 않는다.
disassemble (계속)

disassemble (계속)
그래서 강제로 번지수를 지정해서 디스어셈블 출력을 해 보았다.
/m은 mixed로 소스와 함께 출력해야 하므로 출력이 제대로 되지 않고 /r은 hex data까지 표시되어 난잡해 보이니 아무 옵션 없이 출력하는 게 젤 나아 보인다.
disassemble (추가)
하지만 역시나 Linux의 어셈블러 표기에 익숙하지 않아서 혼란스럽고 이해가 잘 안된다.
Linux 어셈블러 공부마조 또 해야 하나?ㅠㅠ

2014년 10월 25일 토요일

Vim 파일 저장 오류 __ 8

디버그 메시지를 확인하던 중, 메시지의 출력이 되지 않아 확인을 하지 못하고 중단이 되었었다.
SetFileAttr()
하지만 추가적으로 확인해 본 결과, 메시지의 출력은 정상적으로 되었다.
단지, 내가 추가한 부분에 걸리지 않았던 것 뿐.
DOS_SetFileAttr()이 호출되면 중간에는 아무런 문제가 없이 마지막의 GetFileAttr()까지 오는 것이었다.

하지만 소스에서 보듯이 GetFileAttr()은 함수포인터로 호출되므로 정확한 파일 이름을 알 수가 없다.
GetFileAttr() 검색
가상함수인 GetFileAttr()은 드라이브의 종류에 따라 각기 달리 구현되어 있다.
확인해 본 결과 이번 경우에는 drive_local.cpp에 있는 함수가 호출되는 것을 알게 되었다.

그래서 GetFileAttr()에 메시지 추가.
문제가 발생하는 부분은 stat()함수가 실패했기 때문이었다.
GetFileAttr()

stat() 도움말

stat() 도움말 (계속)

stat() 도움말 (계속)

다시 빌드하고 디버그 메시지 확인...

메시지를 봐도 특별히 이상한 점은 찾을 수가 없다.

위의 stat()에 대한 도움말을 읽어 보니, 실패했을 경우에는 errno에 에러 코드를 설정한다고 한다.
그래서 메시지에 errno의 값을 함께 출력하도록 수정.
GetFileAttr()에 메시지 추가

디버그 메시지로 출력된 errno의 값은 2.
debug 출력

errno = 2는 "No such file or directory"...
파일이 없다니....
errno 값의 의미

완전히 막혀버린 상황.
stat() 함수는 기본적인 C 함수이기 때문에, 더 이상의 디버깅을 해도 소용이 없게 된다.
이 문제는 vim의 문제도 아니고 DOSBox의 문제도 아닌 Ubuntu의 문제가 되기 때문이다.

지금으로썬 Ubuntu(혹은 Linux)에서의 DOSBox는 문제가 있다는 것으로 결론을 내릴 수 밖에 없다.

2014년 10월 24일 금요일

Vim 파일 저장 오류 __ 7

예전에 만들어 두었던 debug 버전의 DOSBox를 실행해 보았다.


디버그 터미널에는 여러가지 정보가 표시된다.
DOSBox 화면에서 Alt-Pause를 누르면 디버그 모드를 진입하게 된다.

지금은 디버그 모드로 진입하지 않고 단지 디버그 터미널에 출력되는 내용만 확인해 보았다.

먼저, 기존에 존재하던 "NEWFILE"이라는 파일을 vim으로 열었을 때 디버그 터미널에는 다음과 같은 내용이 출력된다.
"vim NEWFILE"을 실행

파일을 수정하고 ":w"를 입력하여 저장을 시도했다.
역시나 저장되지 않았고, 디버그 터미널에는 다음과 같은 내용이 출력되었다.
수정 후 저장 시도
[Set File Attribute]는 not supported라는 메시지를 출력한다.
아무래도 이 부분이 의심스럽다.

그렇다면 vim이 아닌 다른 에디터는 대체 어째서 문제가 없다는 것일까?
edit를 이용해서 같은 파일을 열어 보았다.
"edit NEWFILE"을 실행

수정을 하고 저장을 해 보았다.
수정 후 저장
Attribute 따위는 아무것도 없다.
file open command의 파라미터가 0인지 1인지에 따라 load/save를 수행하는 듯 하다.
그냥 저장만 하고 끝.

DOSBox의 디버그 메시지에 대해서 자세히 확인하기 위해서는 DOSBox의 소스에서 해당 메시지를 찾아 봐야 하겠다.

DOSBox 소스 검색
"file open command"는 dos_files.cpp의 DOS_OpenFile()에서 출력하는 메시지로, 다음에 오는 숫자는 다음과 같은 의미를 가지고 있다.
0 : read
1 : write
2 : read & write

"file create attributes"는 dos_files.cpp의 DOS_CreateFile()에서 출력하는 메시지로, 다음에 오는 숫자가 attribute를 나타낸다.

"Set File Attributes"는 dos.cpp의 DOS_21Handler()에서 출력하는 메시지이다.
MS-DOS Interrupt Handler를 에뮬레이션 하는 부분인데, 해당 메시지가 출력되는 Interrupt는
AH = 0x43, AL = 0x01, Set File Attribute라고 명시되어 있는 부분이다.

MS-DOS Interrupt, Set File Attributes

그런데 해당 소스를 보면 좀 이상하다.
Interrup Handler가 구현이 안 된것도 아닌데, 아래쪽의 처리를 하기도 전에 "not supported"라는 메시지를 출력하고 있다는 것이다.

일단, MS-DOS Interrupt 21h, ah = 0x43, al = 0x01에 대한 설명을 찾아보면,
디음과 같은 상세한 설명을 볼 수 있다.
MS-DOS Interrupt 21h, ah=0x43, al=0x01

DOS_SetFileAttr()의 소스는 다음과 같다.
소스를 보니, 주석에 설명한 바와 같이 실제로는 파일의 속성을 바꾸지는 않고 파일의 속성을 읽어 올 뿐이었다.
DOS_SetFIleAttr()

그러면 과연 어떤 부분에서 문제가 되어서 에러가 발생하는 것인지 확인하기 위해, 디버그 메시지를 추가해 보기로 했다.
dos.cpp에 메시지 추가

dos_files.cpp, DOS_SetFileAttr()에 메시지 추가

이제 DOSBox를 다시 빌드해야 하는데, 예전에 어떤 설정으로 빌드했는지 모르니 처음부터 다시해야 한다.
디버그 모드로 빌드하기 위해 "./configure --enable_debug=heavy"
DOSBox 빌드, configure

그리고 make
DOSBox, make

이제 DOSBox를 실행하고 아까와 동일하게 "vim NEWFILE" 실행한 경우의 디버그 메시지들을 확인해 보자.
"vim NEWFILE"의 디버그 메시지

그리고 저장했을 때의 디버그 메시지는...
":w"로 저장했을 때의 디버그 메시지
지정한 파일의 속성은 archive(0x20)이고, 에러 코드(2)의 의미는 "file not found"라고 한다.

그런데, 더 구체적인 오류 메시지인 DOS_SetFileAttr()의 메시지는 전혀 출력이 안되었다.
무슨....?
로그 메시지 출력에 어떤 제한이 있는지 다시 확인해 봐야 하겠다.
어차피 실제 속성을 바꾸지 않는 함수인만큼, 오류의 원인을 확인해 보고 별 문제가 아니라면 그냥 성공한 것으로 리턴하게 만들어야 하지 않을까?

나머지는 다음에...