1. http://e2g.org 자료실에 있는 토요 세미나의 UCOS 실행하기 문서를 참고했다.
소스는 아래의 참고 자료에도 링크 해놨으므로 다운받아서 위의 문서를 참고하여 img 파일을 생성한다. 플로피 디스크로 복사하기 전까지, 즉 debug까지 그대로 한다. 소스에 build.bat 라는 파일로 스크립트가 만들어져 있다.
2. VMWare용 부팅 이미지 제작은 여리의 작업실에 있는 Chobits OS 문서를 참고 했다.
부트섹터 부분에 bootsect.bin 대신 소스에 포함된 BOOTSCTR.IMG를 넣어주고, inject하여 MyTask.IMG(컴파일되어 생성된 이미지)를 넣어준다.
3. VMWare의 플로피 부분에 이미지를 선택하고 부팅하면 완성!
p.s 2005.9.11 uClinux에서 uCOS로 카테고리 및 포스트명 변경
p.s2 잠이 와서 대강 썼는데 조만간 자세히 업데이트 해야겠다.
p.s3 다음은 키보드 인터럽트 부분이다
3. 현재의 Shell Prompt를 $시스템이름:현재디렉토리> 형태로 표현될 수 있게 .cshrc or .login 등 리소스 파일을 수정하시오. (수정된 리소스 파일 내용을 새로 적용하기 위해서는 source “리소스 파일”로 수행하면 됩니다.)
4. 현재 디렉토리에 있는 실행파일을 수행시키기 위해 $PATH을 수정하여야 합니다. (1) Shell Prompt에서 수정하는 방법과 (2) 리소스 파일을 수정하는 방법을 설명하시오 (1) export PATH=$PATH:$PWD
(2) .bash_profile 을 수정후 source .bash_profile
5. File mode를 바꾸는 명령어를 찾고, 실제 활용 예를 설명하시오 chmod 755 public_html -> 웹브라우저로 계정 접근 가능
6. cat > notes 를 실행시키면 어떠한 작업을 할 수 있는지 설명하시오 새로운 파일 생성 및 작성
7. 유닉스에서는 Direct Terminal-to-Terminal Communication 방법 (간단한 1:1 채팅)이 있습니다. 실제 활용 예를 설명하시오. talk
8. grep, exec, find 명령을 조합하여 지정 디렉토리 이하 서브디렉토리 아래에서 검색할 문자열이 있는 파일들을 출력하는 Shell Script를 작성하고 활용 예를 설명하시오. grep "찾을문자열" `find . -name '*' -print `
9. Background 및 Foreground 실행에 대해 설명하시오
10. diff 및 comp 명령어에 대해 설명하시오
11. whereis와 같이 유사한 Shell Script를 작성하시오. (whereis에서 제공하는 옵션은 구현하지 않아도 됩니다.)
12. UNIX에서 alias 기법에 대해 설명을 하고 rm 명령어를 interactive 모드로 alias하는 방법을 설명하시오
13. makefile의 한 예를 만들고, 구현한 makefile의 우수성을 보여 줄 수 있는 예제 프로그램들을 구현하여 활용 예를 보여 주시오.
14. gdb를 활용하는 방법에 대한 구체적인 활용 예제를 보여 주시오
15. SIGHUP / SIGBUS / SIGSEGV signal이 무엇인지를 설명하고 SIGBUS와 SIGSEGV를 발생시키는 프로그램을 구현하여 이러한 signal이 발생하는 이유를 설명하고, 해당 프로그램이 정상적으로 동작할 수 있게 수정하시오.
p.s 우리과 유닉스 시스템 수업의 Report 중 하나. 아직 답을 다 못 달았다. 유닉스에 대한 간단한 지식 테스트 및 유용한 것이 많아 올려봤다.
자바 관련 커뮤니티
자바 스터디 : http://www.javastudy.co.kr
자바 서비스넷 : http://www.javaservice.net
제이스톰 : http://www.jstorm.pe.kr
프로 자바 : http://www.projava.com
자바 카페 : http://www.javacafe.or.kr
자바 모델링 : http://www.javamodeling.com
J2EE 스터디 : http://www.j2eestudy.co.kr
JSP School : http://www.jspschool.com
OK JSP : http://www.okjsp.pe.kr
플렉스 개발자 : http://www.flex.or.kr
자바크래프트 : http://www.javacraft.net
자바 유저스넷 : http://www.javausers.net
모바일 자바 : http://www.mobilejava.co.kr
자바지기 : http://www.javajigi.net
OpenSeed : http://www.openseed.net
MS 커뮤니티
코드프로젝트 : http://www.codeproject.com
코드구루 : http://www.codeguru.com
데브피아 : http://www.devpia.com
고수닷넷 : http://www.gosu.net
C# 나라 : http://www.csharpnara.com
Mxpert : http://www.mxpert.net
한국 닷넷 사용자 : http://www.knug.or.kr
CShaper : http://www.csharper.co.kr
태요 : http://www.taeyo.net
Neovis : http://www.neovis.pe.kr
후니 : http://www.hoonsbara.com
mcpworld : http://www.mcpworld.com
WECOM : http://wecom.dstcorp.com
모바일 닷넷 : http://www.mobilemagpie.net
YesPartnet : http://www.yespartner.com/kr/community
데이터베이스 커뮤니티
엔코아컨설팅 : http://www.encore.com
한국데이터베이스 진흥센터 : http://www.dpc.or.kr
DB 구축 운영 종합 : http://www.dbguide.net
데이터베이스 사랑넷: http://database.sarang.net
PostgreSQL 국내 : http://www.postgresql.or.kr
PostgreSQL 공식 : http://www.postgresql.org
오픈소스 커뮤니티
KLDP : http://www.kldp.org
OOPS : http://oops.org
공개 소프트웨어 기술지원 센터 : http://help.oss.or.kr
한글 아파치 사용자 모임 : http://www.apache-kr.org
PHP 스쿨 : http://www.phpschool.com
한국 리눅스 유저 그룹 : http://www.lug.or.kr
리눅스포탈 : http://www.superuser.co.kr
리눅스 문서화 프로젝트 : http://www.linuxdoc.org / http://www.tldp.org
슬래쉬닷 : http://www.slashdot.org
Open Source Development Lab : http://www.osdl.org
Open Source Initiative : http://www.opensource.org
소스포지넷 : http://www.sourceforge.net
플래시밋닷넷 : http://www.freshmeat.net
사바나 : http://savannah.gnu.org 아침에 후배가 사온 마소에서 보니 좋은 커뮤니티가 많이 소개되어 있어 슬쩍 했습니다^^ 혹시 오타가 있거나 링크가 깨어졌거나 알고 있는 좋은 커뮤니티가 빠져있으면 댓글 달아주면 좋겠네요.
2. MP3 player 제작 기본 일정 (2005.09.04)
(1) Atmega 128L에 대한 기본 지식 및 하드웨어 스펙, 프로그래밍 이해
(2) 기본 회로 구성(GPIO, Interrupt)
(3) CF card interface 구성 및 FAT16 파일시스템 구현
(4) ....
- 2.4 GHz, IEEE 802.15.4 compliant
- Tiny, Wireless Measurement System
- FCC Certified
- Designed Specifically for Deeply Embedded Sensor Networks
- 250 kbps, High Data Rate Radio
- Wireless Communications with Every Node as Router Capability
- Expansion Connector for Light, Temperature, RH, Barometric Pressure, Acceleration/Seismic, Acoustic, Magnetic, and other Crossbow Sensor Boards
■ Applications
- Indoor Building Monitoring and Security
- Acoustic, Video, Vibration, and Other High Speed Sensor Data
- Large Scale Sensor Networks (1000+ Points)
- ZigBee Compliant Systems and Sensors
개발 환경..
- CPU : Pentium III 800EB Mhz
- Memory : SDRam 384M
- O/S : Suse 9.2
- Env : KDE 3.3
Suse에서 RPM으로 TinyOS 설치..
1. 여기에 가서 IBM SDK for 32-bit xSeries (Intel compatible) 시리즈를 다운받는다.
- 위의 Clock.setRate부분인데, 원래 nesC에서는 mScale=3 이기 때문에 프로그래머가 Timer.Start의 두번째 인자값인 interval을 양수의 최소값이 1을 넣으면 1/1024(tos/interface/ClockC.nc를 참고)초에 한번 Timer가 발생한다.
- 따라서 mScale=1 로 설정하면 1/32768초에 한번 Timer를 발생시킬 수 있다.
Generic Comm을 이용한 Serial 전송(05.08.10)
일반적으로 tinyOS설치시에 제공되는 TOSBase를 이용하여 serial로 데이터를 받아온다. RF 통신에서는 Generic Comm을 사용하면 여러 종류의 Packet을 쉽게 다룰 수 있는데, 이 Generic Comm을 Serial에서도 사용할 수 있다.
원래 RF와 마찬가지로 Configuration을 비스무리하게 설정할 수 있다.
Configuration
//UART에 대한 sender
SyncNodeM.SendUARTMsg-> Comm.SendMsg[AM_LACKMSG];
- GenericComm을 조금만 사용하본 사람은 눈치챘을 것이다. TOS_UART_ADDR 자리에는 원래 타켓 주소가 들어가는 곳이다.
즉, TOS_BCAST_ADDR 이나 mote의 주소 대신 serial 포트의 주소에 해당하는 TOS_UART_ADDR을 넣으면 된다.
- pc에서 xlisten이나 listen으로 잘 확인할 수 있다.
- 컴파일시 위와 같이 하면 아래 그림처럼 HTML Documentation이 만들어져 어떤 Component들이 연결되어 있는 지 확인할 수 있다. (doc 디렉토리 안에 만들어 생성된다)
CntToLedsAndRfm
Documentation
- 각 노드들의 아이디를 줄때는 다음과 같이 컴파일 한다.
make micaz install,[NodeID] mib510,/dev/ttyS0
05.07.13 - 드디어 졸업과제의 시작이다.
05.07.26 - 서서히 졸업과제 버닝 모드로 돌입하고 있다.
05.08.10 - 낮과 밤이 바뀐 채로 삽질은 계속된다.
05.08.21 - 토익 시험으로 인한 졸업과제 잠시 파업중!
05.08.28 - 토익 시험을 마치고 다시 버닝 모드 돌입! Time Sync에 대한 자료 업데이트 구상중이다.
05.09.01 - 최종 디버깅에 최선을 다하고 있으나, 디버깅할수록 오차가 커져 좌절중이다.
05.09.07 - 박사 과정 한분이 들어오신다길래, 컴퓨터의 소스를 백업했으나, 라이브러리 파일을 백업 안하는 바람에 또 한번 자빠졌다.
05.09.14 - 저녁에 있을 거의 최종 검사때문에 밤샘중... 오차는 어느 정도 줄였고, 라이브러리 파일은 다시 제작했다. 그런데... 베이스가 동시에 데이터를 받지 않는다 orz
05.09.22 - 일주일 빡세게 딴 짓하고(그렇다고 논 건 절대 아니다!), 밤새서 해결했다. 각 노드들이 베이스로 전송하는 시간을 딜레이 주어 다 받도록 하였다. 더불어 MFC 시리얼 통신도 해결!
This is the assembly source for the boot sector used by the Linux free operating system. If it looks unfamiliar for intel assembly, that's because it gets run through the standard C preprocessor (CPP) and has comments starting with '!' stripped off... enjoy! :)
!
! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
! 0x7F00 is 0x7F000 bytes = 508kB, more than enough for current
! versions of linux which compress the kernel
!
#include
SYSSIZE = DEF_SYSSIZE
!
! bootsect.s Copyright (C) 1991, 1992 Linus Torvalds
! modified by Drew Eckhardt
! modified by Bruce Evans (bde)
!
! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
! itself out of the way to address 0x90000, and jumps there.
!
! bde - should not jump blindly, there may be systems with only 512K low
! memory. Use int 0x12 to get the top of memory, etc.
!
! It then loads 'setup' directly after itself (0x90200), and the system
! at 0x10000, using BIOS interrupts.
!
! NOTE! currently system is at most (8*65536-4096) bytes long. This should
! be no problem, even in the future. I want to keep it simple. This 508 kB
! kernel size should be enough, especially as this doesn't contain the
! buffer cache as in minix (and especially now that the kernel is
! compressed :-)
!
! The loader has been made as simple as possible, and continuous
! read errors will result in a unbreakable loop. Reboot by hand. It
! loads pretty fast by getting whole tracks at a time whenever possible.
.text
SETUPSECS = 4 ! nr of setup-sectors
BOOTSEG = 0x07C0 ! original address of boot-sector
INITSEG = DEF_INITSEG ! we move boot here - out of the way
SETUPSEG = DEF_SETUPSEG ! setup starts here
SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536).
! ROOT_DEV & SWAP_DEV are now written by "build".
ROOT_DEV = 0
SWAP_DEV = 0
#ifndef SVGA_MODE
#define SVGA_MODE ASK_VGA
#endif
#ifndef RAMDISK
#define RAMDISK 0
#endif
#ifndef CONFIG_ROOT_RDONLY
#define CONFIG_ROOT_RDONLY 1
#endif
! ld86 requires an entry symbol. This may as well be the usual one.
.globl _main
_main:
#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
int 3
#endif
mov ax,#BOOTSEG
mov ds,ax
mov ax,#INITSEG
mov es,ax
mov cx,#256
sub si,si
sub di,di
cld
rep
movsw
jmpi go,INITSEG
! ax and es already contain INITSEG
go: mov di,#0x4000-12 ! 0x4000 is arbitrary value >= length of
! bootsect + length of setup + room for stack
! 12 is disk parm size
! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We
! wouldn't have to worry about this if we checked the top of memory. Also
! my BIOS can be configured to put the wini drive tables in high memory
! instead of in the vector table. The old stack might have clobbered the
! drive table.
mov ds,ax
mov ss,ax ! put stack at INITSEG:0x4000-12.
mov sp,di
/*
* Many BIOS's default disk parameter tables will not
* recognize multi-sector reads beyond the maximum sector number
* specified in the default diskette parameter tables - this may
* mean 7 sectors in some cases.
*
* Since single sector reads are slow and out of the question,
* we must take care of this by creating new parameter tables
* (for the first disk) in RAM. We will set the maximum sector
* count to 36 - the most we will encounter on an ED 2.88.
*
* High doesn't hurt. Low does.
*
* Segments are as follows: ds=es=ss=cs - INITSEG,
* fs = 0, gs is unused.
*/
! cx contains 0 from rep movsw above
mov fs,cx
mov bx,#0x78 ! fs:bx is parameter table address
push ds
seg fs
lds si,(bx) ! ds:si is source
mov cl,#6 ! copy 12 bytes
cld
push di
rep
movsw
pop di
pop ds
movb 4(di),*36 ! patch sector count
seg fs
mov (bx),di
seg fs
mov 2(bx),es
! load the setup-sectors directly after the bootblock.
! Note that 'es' is already set up.
! Also cx is 0 from rep movsw above.
load_setup:
xor ah,ah ! reset FDC
xor dl,dl
int 0x13
xor dx, dx ! drive 0, head 0
mov cl,#0x02 ! sector 2, track 0
mov bx,#0x0200 ! address = 512, in INITSEG
mov ah,#0x02 ! service 2, nr of sectors
mov al,setup_sects ! (assume all on head 0, track 0)
int 0x13 ! read it
jnc ok_load_setup ! ok - continue
! Get disk drive parameters, specifically nr of sectors/track
#if 0
! bde - the Phoenix BIOS manual says function 0x08 only works for fixed
! disks. It doesn't work for one of my BIOS's (1987 Award). It was
! fatal not to check the error code.
xor dl,dl
mov ah,#0x08 ! AH=8 is get drive parameters
int 0x13
xor ch,ch
#else
! It seems that there is no BIOS call to get the number of sectors. Guess
! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
! 15 if sector 15 can be read. Otherwise guess 9.
mov si,#disksizes ! table of sizes to try
probe_loop:
lodsb
cbw ! extend to word
mov sectors, ax
cmp si,#disksizes+4
jae got_sectors ! if all else fails, try 9
xchg ax, cx ! cx = track and sector
xor dx, dx ! drive 0, head 0
xor bl, bl
mov bh,setup_sects
inc bh
shl bh,#1 ! address after setup (es = cs)
mov ax,#0x0201 ! service 2, 1 sector
int 0x13
jc probe_loop ! try next value
! After that we check which root-device to use. If the device is
! defined (!= 0), nothing is done and the given device is used.
! Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8),
! depending on the number of sectors we pretend to know we have.
seg cs
mov ax,root_dev
or ax,ax
jne root_defined
seg cs
mov bx,sectors
mov ax,#0x0208 ! /dev/ps0 - 1.2Mb
cmp bx,#15
je root_defined
mov al,#0x1c ! /dev/PS0 - 1.44Mb
cmp bx,#18
je root_defined
mov al,#0x20 ! /dev/fd0H2880 - 2.88Mb
cmp bx,#36
je root_defined
mov al,#0 ! /dev/fd0 - autodetect
root_defined:
seg cs
mov root_dev,ax
! after that (everything loaded), we jump to
! the setup-routine loaded directly after
! the bootblock:
jmpi 0,SETUPSEG
! This routine loads the system at address 0x10000, making sure
! no 64kB boundaries are crossed. We try to load it as fast as
! possible, loading whole tracks whenever we can.
!
! in: es - starting address segment (normally 0x1000)
!
sread: .word 0 ! sectors read of current track
head: .word 0 ! current head
track: .word 0 ! current track
read_it:
mov al,setup_sects
inc al
mov sread,al
mov ax,es
test ax,#0x0fff
die: jne die ! es must be at 64kB boundary
xor bx,bx ! bx is starting address within segment
rp_read:
#ifdef __BIG_KERNEL__
#define CALL_HIGHLOAD_KLUDGE .word 0x1eff,0x220 ! call far * bootsect_kludge
! NOTE: as86 can't assemble this
CALL_HIGHLOAD_KLUDGE ! this is within setup.S
#else
mov ax,es
sub ax,#SYSSEG
#endif
cmp ax,syssize ! have we loaded all yet?
jbe ok1_read
ret
ok1_read:
mov ax,sectors
sub ax,sread
mov cx,ax
shl cx,#9
add cx,bx
jnc ok2_read
je ok2_read
xor ax,ax
sub ax,bx
shr ax,#9
ok2_read:
call read_track
mov cx,ax
add ax,sread
cmp ax,sectors
jne ok3_read
mov ax,#1
sub ax,head
jne ok4_read
inc track
ok4_read:
mov head,ax
xor ax,ax
ok3_read:
mov sread,ax
shl cx,#9
add bx,cx
jnc rp_read
mov ax,es
add ah,#0x10
mov es,ax
xor bx,bx
jmp rp_read
read_track:
pusha
pusha
mov ax, #0xe2e ! loading... message 2e = .
mov bx, #7
int 0x10
popa
push dx ! save for error dump
push cx
push bx
push ax
int 0x13
jc bad_rt
add sp, #8
popa
ret
bad_rt: push ax ! save error code
call print_all ! ah = error, al = read
xor ah,ah
xor dl,dl
int 0x13
add sp, #10
popa
jmp read_track
/*
* print_all is for debugging purposes.
* It will print out all of the registers. The assumption is that this is
* called from a routine, with a stack frame like
* dx
* cx
* bx
* ax
* error
* ret <- sp
*
*/
print_loop:
push cx ! save count left
call print_nl ! nl for readability
cmp cl, #5
jae no_reg ! see if register name is needed
mov ax, #0xe05 + 'A - 1
sub al, cl
int 0x10
mov al, #'X
int 0x10
mov al, #':
int 0x10
no_reg:
add bp, #2 ! next register
call print_hex ! print it
pop cx
loop print_loop
ret
print_nl:
mov ax, #0xe0d ! CR
int 0x10
mov al, #0xa ! LF
int 0x10
ret
/*
* print_hex is for debugging purposes, and prints the word
* pointed to by ss:bp in hexadecimal.
*/
print_hex:
mov cx, #4 ! 4 hex digits
mov dx, (bp) ! load word into dx
print_digit:
rol dx, #4 ! rotate so that lowest 4 bits are used
mov ax, #0xe0f ! ah = request, al = mask for nybble
and al, dl
add al, #0x90 ! convert al to ascii hex (four instructions)
daa
adc al, #0x40
daa
int 0x10
loop print_digit
ret
/*
* This procedure turns off the floppy drive motor, so
* that we enter the kernel in a known state, and
* don't have to worry about it later.
*/
kill_motor:
push dx
mov dx,#0x3f2
xor al, al
outb
pop dx
ret
times 512-($-$$) db 0
CPU는 리얼 모드와 BIOS가 0000:7c00에 위치하는 코드에서 시작한다. "times 512..."은 NASM에게 512 바이트를 0로 채워라는 명령이다. 그리고 partcopy는 플로피에 512바이트를 쓴다. (200 in hex = 512) 그것을 변경한다면 partcopy가 말라죽는 것을 보게 될 것이다 ㅠ.ㅜ
종종, 코드 끝에 boot signature(0xAA55) 라고 불리는 것을 보게 될 것이다. BIOS들의 이전 버전들은 디스크에서 부트 섹터를 구별하기 위해 boot signature를 찾았다. 현재에는 명백히 불필요하다. 만약 필요하다면, 마지막 라인에 이렇게 대체해 사용한다. times 510-($-$$) db 0 ;2 bytes less now
dw 0xAA55
그러나 내가 정말로 강조하는 것은 한번 부팅시켜보고, 커서가 빈 스크린에 행복하게 깜빡일 때 2가지를 알아채야 한다. 하나는 플로피 모터가 꺼지는 것과, 다른 하나는 리부트를 위해 Crtl-Alt-Del를 눌릴 수 있어야 하는 것이다.
포인트는 인터럽트(int 0x09)가 여전히 생성되어 있다는 것이다.
재미삼아, interrupt flag를 지워보자 cli
hang:
jmp hang
times 510-($-$$) db 0
dw 0xAA55
플로피 모터가 꺼지지 않는 것과 Ctrl-Alt-Del로 리부트되지 않는 것을 알 수 있다.
여기서 루프를 제거하고, 단지 0로 섹터를 채우는 것에 의해 더이상 줄이려고 한다면,
BIOS는 그것에 대해 어떤 것을 말할 것이다.
"Operating System Not Found".
BabyStep2
Quick review:
- BIOS에 의해 로드되는 부트 섹터는 512바이트이다.
- 디스크 부트 섹터에 있는 코드는 BIOS에 의해 0000:7c00에 로드된다.
- 머신은 리얼모드에서 시작한다.
- CLI가 없으면 CPU는 interrupt가 존재하는 것을 알아낸다.
- 많은(전부는 아니지만) BIOS interrupt는 리얼모드 세그먼트 값을 가지는 DS를 요구한다.
이것이 많은 BIOS interrupt가 보호 모드에서 작동하지 않는 이유이다.
스크린에 출력하는 int 10h/ah=0eh를 사용하려 한다면, 문자들을 출력하기 위해 seg:offset가 올바른지 확인해야할 필요가 있다.
0000:7c00 또는 07c0:0000를 사용한다면 문제되지가 않지만,
ORG를 사용할 경우, 일어나는 일에 대해 알고 있어야한다.
mov ax, 0x07c0
mov ds, ax
mov si, msg
ch_loop:lodsb
or al,al ;zero=end of str
jz hang ;get out
mov ah,$0e
int $10
jmp ch_loop
hang:
jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
dw 0xAA55
times 510-($-$$) db 0
다음은 ORG 버젼이다. 무엇을 DS에 넣을 것인가를 알아야 한다. [ORG 0x7c00]
xor ax, ax ;make it zero
mov ds, ax
mov si, msg
ch_loop:lodsb
or al,al ;zero=end of str
jz hang ;get out
mov ah,$0e
int $10
jmp ch_loop
hang:
jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
dw 0xAA55
times 510-($-$$) db 0
새로운 주제 : 전형적인 procedure는 코드로 부터 CALL/RET 같은 것을 사용하여 구분되었다.
[ORG 0x7c00]
xor ax, ax ;make it zero
mov ds, ax
mov si, msg
call bios_print
hang:
jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
bios_print:
lodsb
or al,al ;zero=end of str
jz done ;get out
mov ah,$0e
int $10
jmp bios_print
done:
ret
dw 0xAA55
times 510-($-$$) db 0
몇가지 설명할 수 없는 이유로 때문에, SI 로딩하고 procedure로 점프하는 방법은 나를 놀라게 했다. 운좋게 나같은 사이코들을 위해, NASM의 매크로는 파라메터 패싱을 허용하고 있다. %macro BiosPrint 1
mov si, word %1
ch_loop:lodsb
or al,al ;zero=end of str
jz done ;get out
mov ah,$0e
int $10
jmp ch_loop
done:
%endmacro
[ORG 0x7c00]
xor ax, ax ;make it zero
mov ds, ax
BiosPrint msg
hang:
jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
dw 0xAA55
times 510-($-$$) db 0
만일의 경우 코드는 길어지고, 읽지못하게 될 수 있다. 메인 코드의 시작에 파일을 include 함으로써, 다른 파일로 분할할 수 있다. jmp main
%include "othercode.inc"
main:
;... rest of your code here
BabyStep3
기계어에서 Opcode
; nasmw encode.asm -f bin -o encode.bin
mov cx, 0xFF
dw 0xAA55
times 510-($-$$) db 0
디스크에 partcopy를 하지 않는다.
단지, DEBUG를 연다. ( MS*에서는. 리눅스 유저들은 Hexdump가 좋다)
C:osdevdebug encode.bin
바이너리 파일을 보기 위해 '-' 이후에 'd'를 타이핑한다.
('?'는 help, 'q'는 quit)
이와 같은 것을 보게 될 것이다.
OAE3:0100 B9 FF 00 00 00 00 etc...
MOV에 대한 opcode를 찾으려면 여기를 보라 htp://www.baldwin.cx/386htm/MOV.htm
바꾸어 말하면, 덤프에서 보이는 것은 유니크 레지스터 넘버(unique register number)(CX = 1)가 기본 opcode 값인 'B8'에 주어진 'B9'를 더한다.
하지만, CX를 ECX로 대체할 시, 발생하는 일을 보자. mov ecx, 0xFF
dw 0xAA55
times 510-($-$$) db 0
OAE3:0100 66 B9 FF 00 00 00 00 etc...
'66'은 32Bit operand size를 가지는데, NASM이 바이너리 파일은 16Bit로 어셈블되므로, 모순된다.
모드를 변경하기 위해 BITS directive를 사용한다면 같은 일이 발생한다.
하지만 operland의 사이즈와는 다르다. [BITS 32]
mov cx, 0xFF
dw 0xAA55
times 510-($-$$) db 0
이것으로 프로세서의 모드가 실제적으로 변경되지 않는다.
단지, 이것은 다음의 byte 해석을 돕기 위한 것이다.
Addresses
주소 인코딩(Address encoding)은 더 복잡한 bit이다. mov cx, [temp]
temp db 0x99
dw 0xAA55
times 510-($-$$) db 0
OAE3:0100 8B 0E 04 00 99 00 00 00 etc...
'8B'는 opcode이다.
'0E'는 opcode를 해석하는 데 도와주는 ModR/M이다.
"17.2.1 ModR/M and SIB Bytes"를 참고 : http://www.baldwin.cx/386htm/s17_02.htm
(Fig. 17-2를 보라) 다른 필드를 가지는 이 byte를 해석하기 위한 룰은, 운좋게 Table 17-2는 그것을 쉽게 만들었다.
'0E'를 보고, 왼쪽에 있는 "disp16"를 볼 것이다. operand는 16bit offset으로 해석된 의미이다.
'04 00'은 16-bit offset이다. 0x0004가 왜 거꾸로인지 혼란스러울지 모른다. Intel Processor는 리틀 인디안(little endian) 이기 때문이다.
'99'는 물론, 0x0004에 있는 byte의 값이다.(8B는 0x0000에 있다)
Be aware of another prefix called the Address size Override Prefix '67' which the assembler generates when there is a discrepancy just like with '66' above. (해석 불가 ㅡㅅㅡ;;)
16-bit 리얼 모드에서 32-bit 보호 모드로 전환하기 위해 코드는 변경될 것이다.
BabyStep4
이 예제는 문자열과 메모리의 내용(비디오 메모리에서 문자열의 첫글자)을 출력한다.
이것은 BIOS를 사용하지 않고 텍스트 모드에서 스크린에 출력하는 예제를 의미한다. 게다가 변환된 hex는 화면에 출력될 수 있다. 그러면 레지스터와 메모리 값을 체킹할 수 있는 것이다.
stack을 더했지만, 그것을 사용하여 끝내지 않았다. 그러나, 아마도 곧 사용할 것이기 때문에 남겨두었다.
mov ss, ax ; 스택은 0에서 시작한다.
mov sp, 0x9c00 ; 200h 지나서 코드가 시작한다.
mov ax, 0xb800 ; 텍스트 비디오 메모리를 저장한다.
mov es, ax
mov si, msg ; 텍스트 스트링을 보여준다.
call sprint
mov ax, 0xb800 ; 비디오 메모리를 본다.
mov gs, ax
mov bx, 0x0000 ; 'W'=57 attrib=0F
mov ax, [gs:bx]
mov word [reg16], ax ;Register를 본다.
call printreg16
hang:
jmp hang
;----------------------
dochar:
call cprint ; 문자하나를 출력한다.
sprint:
lodsb ; 문자열(si)에서 문자 하나를 al에 저장한다.
cmp al, 0
jne dochar ; 0이 아니면 문자를 출력한다.
add byte [ypos], 1 ; 한 라인 밑으로 (CR)
mov byte [xpos], 0 ; 왼쪽 끝으로 이동 (LF)
ret
cprint:
mov ah, 0x0F ; attrib = white on black
mov cx, ax ; 문자의 속성을 저장한다.
movzx ax, byte [ypos]
mov dx, 160 ; 각 문자는 2바이트를 잡아먹는다(문자 + 속성) 2*80 = 160
mul dx ; 80컬럼이기 때문(dx는 한 라인의 정보를 저장하는 것 같다)
movzx bx, byte [xpos]
shl bx, 1 ; 속성을 skip하기 위해 2를 곱한다.
mov di, 0 ; 비디오 메모리의 시작
add di, ax ; y좌표를 더한다.
add di, bx ; x좌표를 더한다.
mov ax, cx ; 문자와 속성을 불러온다.
stosw ; 문자와 속성을 쓴다.
add byte [xpos], 1 ; 오른쪽으로 한칸 이동
hexloop:
rol ax, 4 ; 가장 왼쪽은 (4바이트 왼쪽으로 로테이트)
mov bx, ax ;
and bx, 0x0f ; 가장 오른쪽이 된다.
mov bl, [si + bx] ; index into hexstr
mov [di], bl
inc di
dec cx
jnz hexloop
mov si, outstr16
call sprint
ret
;------------------------------------
xpos db 0
ypos db 0
hexstr db '0123456789ABCDEF'
outstr16 db '0000', 0 ;register value string
reg16 dw 0 ; pass values to printreg16
msg db "What are you doing, Dave?", 0
dw 0xAA55
times 510-($-$$) db 0
;==================================
※ http://www.mega-tokyo.com/osfaq2/index.php/BabyStep 에서 가져왔습니다. 그대로 해석하기 보다는 저가 공부하고 있는 입장에서 저가 보기 편하게 해석했습니다^^
요즘 블로그의 대세는 바톤 넘기기인 듯합니다.
음악, 게임, 노래방, 블로그 바톤 넘기기... 외 기타 등등..
참 배경화면 바톤 넘기기도 있던데..
누가 시작했는지는 모르지만...
일요일 저녁...
자다가 일어나 테터센터를 돌고 있는데 문득 생각이 들었네요. 엥? 왜 리눅스 바톤 넘기기는 없지 ㅡ_ㅡ?
그.래.서. 리눅스 바톤 넘기기 5문 5답을 시작합니다!
온라인쪽에 별로 아는 사람들이 없어서, 바통이 제대로 넘어갈 지는 모르겠네요. 그래도 출!발!합니다.
1. 가장 처음으로 사용했던 리눅스 배포판...
제일 처음 사용했던 배포판은 slackware 3.4였다. 98년도 대학 입학하자 마자, 모 동아리 선배의 압박에 못이겨, 거금을 투자하여 리눅스가 있는 시디를 구입했었다. 지금은 안타깝게도 우리나라에서는 거의 사장되어 가는 듯.
2. 가장 최근에 설치했던 리눅스 배포판... 임베디드 관련 수업때, 사용한 slackware 9.1. 다들 redhat 계열을 설치했으나, 무슨 만물상도 아니고 시디에 다 때려넣어놨기에 마음에 안들어서 slackware를 선택했다. (그런데, slackware는 진짜 불친절한 배포판이다. 무슨 말인지 궁금하면, 한번 깔아봐요~. 왜 불친절한가..)
이전에 설치한 ubuntu 5.04와 요사이 빈 하드에 새로이 설치한 suse 9.1. 데스크 탑용으로 쓰려고 두 배포판을 설치했는데, 현재 suse 탐험 계획을 가지고 있다. ubuntu는 live CD 만든다고 한번 미쳐서 설치한 이후 제거되지 않고 있다.
3. 가장 마음에 드는 윈도우 매니저는...
- Qt 공부하면서 KDE가 더 좋아졌다. 뭐 gnome이 싫다는 것도 아니지만, 요즘 친숙한 건 KDE다. 우리나라는 gnome이 대세라고 하던데. 눈치보고 바꿔야지..ㅋ(얼마전 kldp에서 슬쩍 읽은 듯한..)
4. 자주 사용하는 리눅스 프로그램 5가지...
- 처음, 당연히 vi가 제일 많이 사용하지 않을라나? 늘 vi vs. emacs가 논제로 펼쳐지지만(지금도 kldp 어디에서가...) 나 역시 emacs는 너무 어렵다. 요즘 실습 시간에 리눅스 설치해야한다고 하면, emacs는 일단 설치에서 제외 대상 1호가 되어버린다.
- 둘, 나 역시 무늬나마 컴퓨터 공학도(?)로서, gcc 사용 빈도가 높지. 그런데, 컴파일러도 프로그램에 들어가겠지? 프로그램에 안들어 갈라나?
- 셋, 역시 리눅스하면 인터넷. ubuntu를 사용할 때는 firefox를, suse를 사용할 때는 conqurer(철자가 맞나?)를 사용하는데, firefox에게 점수를 더 주고 싶고, 더 자주 사용한다.
- 넷, mplayer랑 xmms. 프로그래밍할 때, 웹서핑할 때 음악이 없으면 무슨 재미로 산다냐?
- 다섯, 헉... 내가 사용하는 프로그램이 이렇게 없었단 말인가. 아~ 방금 머릿 속에서 먼가 지나쳐갔다. gFTP가 있었지. 한글 디렉토리는 제대로 안보는 단점(slackware에서만 그런가?)이 있지만, 손수 console로 접속하는 것보다 훨~씬 편리함을 제공하고 있다.
5. 다음 바통을 이어바으실 분...
자신이 리눅스의 마력에 끌린다고 생각하시는 모든 분들...
리눅스에서 산전수전 다 겪어보신 분들...
자신의 컴에 현재 리눅스가 설치되어 있으신 분들~
감사히 트랙백 받겠습니다! (과연 날라올까 ㅜㅜ)흠.. 어제 포스트 작성하고 나서 계정이 뻗었다가 (솔직히 저의 불찰입니다 ㅜㅜ) 만 16시간만에 살아났네요 @.@ 그래서 다시 포스팅 합니다 우어~~
- 토익 말아먹고 전산실에 와서 EJB 프로그래밍 디플로이먼트 부분을 맡아서 연재(?) 하게 됐네요~ 앞에 선배가 너무 잘 해놔서 머.. 그만큼은 못되겠지만서도..;;
함 해보입시다~
1. Deployment Tool 을 띄웁니다. (좀 마이 느리네요;;)
2. Entity Bean 을 생성합니다.
- 우리가 Eclipse 실행시에 지정한 폴더안에 User 라는 project 명의 폴더가 있습니다. 그 안에 각 package 별로 폴더가 만들어져 컴파일된 class 파일이 있습니다.
- 그걸 Edit Contents 할 때 폴더를 지정하고 Add 를 합니다.
- Entity Bean 이 Local Interface로 되어있으므로 그림과 같이 Local interface 안을 지정해 줍니다.
- DB에 저장할 필드를 체크해 줍니다. (우리는 name 과 id를 체크하면 되겠지요~)
그리고 primary key 에 해당하는 필드를 지정해 줍니다. (앞에서 id를 string class로 정의한 것은 이것때문이라네요. 즉, primary key는 클래스여야 하기때문이죠. string 대신에 Integer 사용해도 되겠죠)
Next~
- DB 설정을 합니다.
왼쪽트리에서 UserInfoBean 을 선택하고 오른쪽에서 Sun specific setting 버튼을 누릅니다.
그림과 같은 창이 하나 뜨고 view 부분에서 CMP database 를 선택합니다.
오른쪽 위에 있는 create database mappings 버튼을 클릭합니다.
-위와 같은 창이 뜨지요?
그 창에서 건드릴껀 없고 고마 OK를 누릅니다. (알아서 DB 스키마가 생성된다네요)
-그러면 위와 같이 DB가 생성된 것을 볼 수 있습니다~
3. Session Bean 을 생성합니다.
Entity Bean 과 동일한 방법으로 폴더를 선택합니다.
- Next를 눌리면 위와 같은 그림이 뜹니다.
앞서 Entity Bean 때는 Local Interface 를 선택했었는데 이번에는 Remote Interface 를 선택합니다.
- 고마 Next 눌러서 Finish 합니다.
왼쪽 트리에서 UserManageBean을 선택하고 오른쪽 탭에서 EJB Ref's를 선택합니다. (Ref's는 현재 Bean에서 다른 Bean으로 참조할 때 사용됩니다.)
그러면 위와 같은 창이 뜨고 그림과 같이 다 설정을 해줍니다.
Coded Name에는 앞 강좌에서 사용되었던(!) ejb/UserInfoEJB를 적어줍니다. 즉, UserManageBean에서 UserInfoBean으로 접근시에 lookup에서 사용한 이름을 적어줍니다. java:/comp/env는 제외하고요. (우형선배가 이거땜에 이틀을 삽질했다고 광분(?) 을 하시며 강조하시네요)
4. JSP 를 web component 로 등록합니다. (자세한 건 이전 강좌 참조하세요)
설정부분만 하겠습니다.
- 위 그림처럼 왼쪽 트리에서 WebApp 를 선택하고 오른쪽 탭에서 EJB Ref's 를 선택합니다.
그러면 뜨는 창에서 이름은 앞서 코드(Client.jsp 에서의 lookup부분)에서 썼던 이름을 쓰고 그림과 같이 설정해 줍니다. (client.jsp에서 UserManageBean으로 접근하기 위해서 사용된 이름입니다. )Interface 는 Remote Interface 로 설정합니다.
5. Deply 합니다. (이제 막바지에 다왔답니다~ 이거 그냥 볼때는 몰랐는데 직접 만들어보니까 장난아니게 귀찮네요 ㅡ.ㅡ;)
아무 오류 없이 successful 이 나오면 성공한겁니다~~ 대단하다~
6. 웹 브라우저 실행
-Web Component에서 Context Root를 ContextRoot로 설정하고, client.jsp의 alias를 Cool로 설정하였습니다.
-일단 웹에서 접속한 결과 아무런 메시지가 안나오는 군요.
7. Pointbase에 제대로 들어갔는지 확인해봅시다. (C양이 집중력이 떨어져 다시 바통을 이어받습니다.)
총 4회에 걸쳐 jsp-session-entity-db 까지 간단히 연동해보았습니다. 간단히 db에 입력하는 것만 했는데요. 약간만 응용하면 충분히 다른 오퍼레이션도 설정이 가능합니다. 앞으로 각자 공부해야할 것들은 PK Class와 find method에 대해서 충분히 공부해야할 듯하네요.
※ 덧 : 며칠동안 삽질하던 저에게 한마디로 깨우침을 준 우리 조원인 고모씨의 아들, 동진군에게 감사의 말을 전합니다. 또한 옆에서 지켜봐주고, 마지막 회를 열심히 타이핑하다가 지겨워서 포기한 C양에게도 감사의 말을 전합니다.. ㅋ
- 이 파일에서는 create가 선언되어 있습니다. UserInfoBean.java 파일안에서 ejbCreate로 구현이 되어 있구요. XDE로 생성한 코드는 뒤에 인자가 들어가지 않습니다! 우리가 만들 Entity Bean은 id와 name을 가지므로 create함수의 인자를 그림처럼 선언해줍니다.
UserInfoBean.java
- 위에서 create함수에서 선언한 부분을 이 파일의 ejbCreate함수에도 동일하게 선언을 해주고, 구현합니다. (set 함수를 이용하면 되겠죠.)
- 또 하나 주의할 점이 있습니다. 바로 ejbPostCreate함수인데요. 원래 XDE에서 생성해주지만, 그림에서 블록으로 지정된 부분처럼 하나 더 만들어줘야 합니다. ejbCreate함수의 인자와 동일하게요. (상당히 삽질했습니다. 이 부분이 없으면 나중에 ejbCreate 함수를 찾을 수 없다고 투덜됩니다..)
- 이정도이면 UserInfo에 대한 정리는 끝났습니다.
2. 두번째, UserManage 클래스들의 소스 화면입니다.
UserManageBean.java
- 먼저 UserManageBean.java 코드의 앞부분에 블록 지정된 부분처럼 import를 합니다. Entity 패키지에 있는 UserInfo를 여기서 접근해야하기 때문입니다.
- 우리가 XDE에서 만든 register함수를 구현할 차례입니다. 위에서 import한 javax.naming.*은 UserInfo의 Home Interface를 찾기위해서입니다. (Context 클래스를 사용하죠^^)
- 블럭부분으로 지정된 부분을 잘 기억해주세요. 특히 ejb/UserInfoEJB를 기억해둬야합니다. JNDI및 EJB Ref 설정시 필요합니다.
- eclipse는 저장시 자동으로 컴파일이 됩니다. 따라서 변경하고 저장을 합니다.
3. Session Bean에 접근할 JSP 파일을 하나 만들어 봅시다.
- 간단히 프로젝트 명에서 우클릭하여 JSP를 선택합니다.
- 파일명을 넣어줍니다. (jsp 확장자도 넣어줘야합니다.)
client.jsp
- 여기서 할 얘기가 조금 많습니다. 일단 import 부분부터 언급해야겠네요.
page import="javax.naming.*" ==> Class를 찾기 위해서
page import="javax.rmi.*" ==> Remote Interface에 접근하기 위해
page import="Session.*" ==> UserManage가 포함된 패키지
- 다음은 body 이하의 부분입니다. Local Interface에 접근하였던register함수 구현부와는 달리, JSP에서는 Remote Interface에 접근해야하므로 PortableRemoteObject를 사용해야합니다. 접근 방식이 다르므로 눈여겨 보아야합니다. (48시간 삽질 부분입니다!) 역시나, lookup 부분을 기억해둬야합니다.
4. 자 전체적인 소스의 흐름에 대해 설명합니다.
(1) client.jsp에서 Session Bean인 UserManageHome(Remote Interface)을 찾습니다. (lookup 부분 과 PortableRemoteObject)
(2) UserManageHome에서 UserManage를 받아옵니다. (home.create() 부분)
(3) UserManage에서 register를 호출합니다.
(4) register 함수에서는 EntityBean인 UserInfoHome(Local Interface)를 찾습니다. (lookup 부분)
(5) UserInfoHome에서 jsp에서 받아온 field를 인자로 넣어, UserInfo를 생성합니다.
- 인터넷이나 책에보면 잘 나와있으므로, 여기서는 개념보다는 방법을 설명하도록 하겠습니다.
자~ 이제 소스 프로그래밍 파트는 다 끝났습니다. 이제 디플로이먼트가 남았네요. 디플로이먼트 파트는 C양이 받아서 하겠습니다^^
1. 간단한 XDE 설계
- 왠만하면 무거운 XDE를 사용하고 싶지 않으나, Generate Code라는 기능 때문에 간단히 XDE에서 설계한 후 Code를 생성하여, eclipse에서 가져오겠습니다. XDE를 사용하기 귀찮으신 분은 바로 eclipse에서 코딩해도 무방합니다^^
- 일단 Project를 생성합니다. Project 폴더도 설정합니다.
- Use-Case Model를 생성하고, Class 2개 만듭니다. 하나는 Control Class(UserManage), 나머지는 Entity Class(UserInfo) 입니다.
- 다음으로 각 Class의 stereo type을 정합니다. 각각 Control과 Entity type을 가지겠지요^^ (XDE가 무겁긴 무겁군요. 그림판 2개 띄우다가 컴이 뻗어버렸습니다 ㅡㅡ)
- 이제는 각 Class에 필요한 method와 field를 넣습니다. 참고로, Entity Class의 set/get method는 XDE에서 생성해주므로 넣을 필요 없습니다.
-> 저는 Control Class 안에 register함수를 만들었습니다.
- 분석단계의 Class를 다 만들었으므로, EJB 객체를 만들어봅시다.
파일 -> 신규 -> 모델 메뉴를 차례대로 따라가면, 아래의 다이얼로그가 뜹니다. EJB Code Model을 선택합니다. 그러면 EJB Code Model를 추가되는 것을 Model Explorer에서 확인할 수 있습니다.
- 우리가 생성한 Class위에서 우클릭하여 Transform 합니다. Entity Class는 CMP 2.0 Entity Bean으로, Control Class는 Stateless Session으로 Transform합니다. Transform은 EJB Code Model에서 확인할 수 있습니다.
-> 여기서는 Entity Bean과 Session Bean을 같이 두었는데, 보통 패키지로 따로 묶습니다. 저 또한 Entity와 Session 패키지를 만들어 따로 Class를 넣어두었습니다. 이렇게 하는 것이 나중에 Generate Code 이후에 java 소스가 알아서 폴더별로 들어가므로 관리하기 편할 껍니다.
- 각 클래스를 선택한 후 우클릭하여 Generate Code를 합니다.
- 여기까지 이상없으 진행이 되면 처음 Project 생성할 때 지정한 폴더 하위 폴더에 Entity와 Session 클래스가 생성되어 있고, 그 안에 java 소스가 생성되어 있는 것을 확인할 수 있습니다.
여기까지가 간단한 설계과정입니다. 원래 JSP나 Servlet도 같이 해야겠지만, 거기까지는 삽질하지 못한지라... (나름대로 바쁩니다 ^^)
담배하나 피우고, #2로 넘어갑니다..