2011년 6월 10일 금요일

life] 대한민국 위키를 보다가 포스팅.

출처 : 위키피데아

평가기관 항목 순위 조사 시기


프리덤하우스(세계인권단체) 정치인권 및 시민자유 자유(Free)
국경 없는 기자회 인터넷 통제 인터넷 감시 대상국[97] 2010년
레가툼 연구소 개인적 자유 104개국 중 70위[133] 2009년
-------------------------------------------------------------------------
몽미... ㅋㅋ


스위스 국제경영개발원(IMD) 노동 생산성 57개국 중 1위[84] 2009년
--------------------------------------------------------------------------

졸 빡시게 일하는거야 우린ㅠㅠ


세계은행 관세행정 61개국 중 1위[99] 2009년

--------------------------------------------------------------------------

대원군 쇄국정책 먹혔넹. 그래도 보호할 건 하고 세계로 나가야지.





옥스퍼드대학교, 오비에도 대학교 초고속 인터넷 품질 66개국 중 1위[100] 2009년
아카마이 인터넷 평균 속도 226개국 중 1위[105] 2010년 1분기
------------------------------------------------------------------------
인터넷 열라 빨라.





WEF(세계경제포럼) 유선 인터넷 요금 138개국 중 67위(순위가 낮을수록 비쌈)[106] 2011년
------------------------------------------------------------------------
요금은 평균




세계경제포럼(WEF) 광대역 인터넷 가입자수 134개국 중 4위[113] 2008년

미국CIA 월드팩트북 인터넷 사용자 237개국 중 10위[123] 2010년
--------------------------------------------------------------------------

사람도 얼마 안되는데 ㅡㅡ; 비율도 아니고 수



통계청(OECD국가들 중) 인터넷 이용률 30개국 중 7위[104] 2009년
--------------------------------------------------------------------------

온라인 게임도 포함시켜달라!!





통계청(OECD국가들 중) 선박 건조량 30개국 중 1위[104] 2009년

Clarkson PLC 사 조선산업 경쟁력 15개국 중 1위[98] 2008년

--------------------------------------------------------------------------


동민아 STX는 빡실수 밖에 없는거야.





경제 협력 개발 기구(OECD) 교통사고 사망률 38개국 중 1위[101] 2007년
경제 협력 개발 기구(OECD) 결핵사망률 30개국 중 1위[102] 2005년
경제 협력 개발 기구(OECD) 제왕절개분만률 1위[103] 2005년
통계청(OECD국가들 중) 10만 명당 자살률 30개국 중 1위[104] 2007년
------------------------------------------------------------------------
운전 살살. 제왕절개는 왜케 많지... 누가 댓글 좀...
결핵 징후는 포스트 젤 마지막에 첨부.
자살은 왜할까?


 행복하지 못하다.
NEF 행복지수 143개국 중 68위[136] 2009년

 경제력에 비해 삶의 질이 떨어진다.
인터내셔널 리빙 삶의 질 194개국 중 42위[148] 2009년

 그래서 애도 못낳겠다.
미국CIA 월드팩트북 인구증가율 237개국 중 179위[123] 2010년

미국CIA 월드팩트북 출산율 237개국 중 219위[123] 2010년


 있는 애도 자살 ㅠ.ㅠ
경제 협력 개발 기구(OECD) 청소년 자살률 30개국 중 15위[122] 2009년



부모님들 뼈빠지게 등록금 내주고
경제 협력 개발 기구(OECD) 대학 등록금 36개국 중 2위[109] 2009년



열라 공부해도.
 경제 협력 개발 기구(OECD) 학업성취도(수학, 과학, 문해, 문제해결력), 교육수준 30개국 중 2위[107][108] 2009년





 취업도 안되니까...
OECD 청년 고용률 29개국 중 28위[139] 2010년



나머진 여기에
http://ko.wikipedia.org/wiki/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD

그리고 가장 중요한...

세계경제포럼(WEF) 남녀평등지수 134개국 중 104위[152] 2010년
잘하자... 여자친구에게 어머니, 할머니께, 여동생에게, 이모, 고모, 숙모, 식당 아주머니, 청소하시는 아주머니, 보험하는 분 등등...

 
일차성 폐결핵 — 일부 사람들, 특히 어린 소아들은 발열과 피로 이외에 다른 증상이 없습니다. 다른 증상들로는:



o 기침


o 흉통


o 야간 발한


o 식욕 부진


o 체중이 늘지 않음


• 재활성화 폐결핵— 증상으로는:


o 발열


o 야간 발한


o 체중 감소


o 식욕 부진


o 무기력


o 흉통


o 기침


o 전신 쇠약감






결국은 색이 변한 가래가 섞인 기침도 대개는 발생합니다. 질병이 진행함에 따라서, 환자들은 피를 토하고, 호흡이 곤란해지고, 결국은 심한 호흡 문제를 겪게 됩니다.






• 폐 외 결핵— 증상은 결핵이 어디로 퍼졌는지에 따라서 다릅니다. 예를 들어, 결핵이 림프절로 퍼졌다면, 대개는 목 기저부와 양 옆쪽의 림프절이 붓게 됩니다. 뼈와 관절 결핵에서는, 척추, 고관절, 무릎이 감염이 가장 흔하게 일어나는 부위입니다. 관절은 아프고 붓게 됩니다. 비뇨생식기 결핵이 있으면, 옆구리(늑골과 고관절 사이) 통증, 잦은 배뇨, 배뇨 중 통증이나 불편 감, 혈뇨가 있을 수 있습니다.


• 파종성 또는 속립 결핵— 증상으로는:


o 발열


o 야간 발한


o 체중 감소


o 무기력


o 폐의 문제(기침, 호흡 곤란, 흉통)


결핵균이 전신으로 퍼지더라도 아무런 다른 증상이 없을 수도 있습니다. 하지만, 증상이 있다면, 거의 어디에서든지 나타날 수 있습니다. 더 흔한 증상들로는:


o 두통


o 시각 장애


o 림프절 부종


o 관절통


o 고환에 덩어리 형성


o 피부 발진


o 복통
 
출처 : http://www.vitaminmd.co.kr/dic/disease/harvard/view.md?diseaseid=000pl

tip] github

마켓에 올려진 이미지 뷰어 업뎃은 없을 것 같아서 공개시켰다.

github에

커맨드 라인 commit 방식이라 그런지 나중에 손에 익으면 "빠"가 될 것 같네.

인터넷 찾아 보니 쿠폰 있던데

WWDC11

Plans & billing 에서 couporn 코드 입력하면 30days micro plan이 무료다.

https://github.com/hajunho/Bicture

P.S 애플빠가 세상에 많군. 나도~ ㅋㅋ

win] cmd 원하는 디렉토리에서 실행.

윈도우키 + R
cmd

많이들 쓴다.

더 편하게.

cmd.exe /k cd "C:\"

레지스트리에 꽂아 넣어서 expolorer에서 바로 실행하는 방법도 있지만
위의 방법을 쓰고

cmd안에서

expolorer .      <- 쩜(.) 중요

해서 역으로 탐색기를 여는 방법이 더 편할 때가 있다.

2011년 6월 8일 수요일

tip] 7zip의 tar와 win tar는 다르다.

댄장.

7zip에도 tar 압축 기능이 있어서...

믓튼 압축하고 나면 미묘하게 다르다 ㅠ.ㅠ

25) 미국 반지 사이즈

한국이랑 다르다.

ㅡㅡ; 쩝.

이미 세팅이 끝나고 발송된 물품이라서 그랬나보다.

반지 줄이는데 10만원 추가 ㅠ.ㅠ

2011년 6월 7일 화요일

android] superoneclick download

http://forum.xda-developers.com/showthread.php?t=803682

2011년 6월 5일 일요일

life] 시계가 비싼 이유.

메이커 가격이 워낙에 비싸서.

코카콜라 시계 나오면 기본 3억은 하긋네.

라는 건 우스개고...

오랫동안 장인들이 이어온 명성을 같이 사는 거니까.

하지만 아무리 장인이라도 수공예로 반도체 칩은 못만드는데.

나 역시 아날로그 시계에 빠져 허우적댄적이 있어서 말할 수 있는 것인데

왜 오차가 많이 나는 수동 태엽 시계가 가장 땡기고

그래도 오차나는 오토매틱 태엽 시계가 땡기고

아날로그 시계가 땡기고.

그 다음 디지털 시계가 땡기는지 모르겠다.

다 사람들 시선 때문.

시간을 정말 소중이 여긴다면 가벼운 디지털 시계를 차는 것이 맞는 것 같다.

반도체가 대중화 되지 않았다면 숫자 디지털 시계는 최소 10억은 했을거다.

뭐.. 대중화 되었으니까 만들수 있는 자본이 되었겠지만.

믓튼, 시간은 소중하다.

24) 시계

시계는 미국도 비싸다.

시계 자체도 비싸지만 수리비는 더하다.

전에 시계 들고 고치러 갔드만

무브 나갔다고 200불이란다.

댄장... 시계가 100불 안하는데.

물론 무브가 더 좋긴 하겠지.

23) coach 가방

미국서 사면 많이 싸다.

반값? 아니면 그 이하?

하지만 최신 라인업은 똑같이 비싸지.


항상 시간이 중요하다.

life] 글쓰기가 중요한 이유.

보고서를 쓸 때.

빡시게 일한 사람은 몇 줄 적을게 없는데

일 안한 사람은 적을게 많다.

그래서 글쓰기가 중요하다.

그리고 그것의 차이를 볼 줄 아는 능력도 중요하다.

life] 자살 유행...

연예인들 자살 몇명이나 했는지 궁금했는데 잘 정리된 사이트가 있었다.

http://pporidad.tistory.com/21

다는 없지만.



자살이 이해가 안가는 것은 아니지만.

연예인이라면 최소한 이유는 확실히 적어두고 가야 할 것이라 생각된다.

너무도 큰 사회적 파장을 몰고 오기 때문이다.

상처를 준 사람들은 대중이 아니고 대부분 특정인들이기 때문이다.

하긴 ... 자살 하는 사람 심정이 어떤데 그런 걸 생각할 겨를이나 있겠나.

그래도 뉴스에 나오고 애도하는 사람이라도 많지.

그리고 먹을 것도 못 구하는 사람들도 살아 가는데 그런 사람들에게

자살보다 나은 희망은 주어야 하지 않겠나... 싶다.

좋아하던 연예인들만 죽는 것 같아 속도 쓰리고 자살에 관해서 오래도록 생각했지만

정작 논리적으로 쓰려고 하니 할말이 없다.

 그들의 마음을 모르니까. 뭐, 이해 못할만한 인생을 산 것은 아니지만. 그 당시의 그 고통.

그것을 모르니까.

 안다고 말은 못하고 다만. 그러지 말았으면 한다.

왜 죽어야 하는지 이유를 쓰다보면 생각이 달라지지 않을까?

2011년 6월 4일 토요일

망상 7

세상은 공평하지 못하고, 완전하지도 않다. 결국.

어릴적에는 그걸 몰랐었다.

회사 생활도 그렇다. 공평하지도 완전하지도 않다.

하지만 당장 그것을 새로 시작하는 사람들에게 보여 줄 필요는 없다는 것 깨달았다.

아니, 안 보여 주도록 지켜 나가야 한다는 것을 알았다.

나만의 세상에 다른 사람의 생각을 가두려는 것은 아니지만.

척박한 세상에 작은 행복들을 만들어가는 수많은 사람들을 쉽게 찾아 볼 수 있기 때문에.

그래도 그런게 아니라는 말을 하면서.

만들어 가야한다.

새로운 시작이다.

2011년 6월 3일 금요일

asm] 어셈러브 강좌 펌 6

제 8 장 . 반복 기법--------------------------------------------------------------------------------8.1 루프(loop)명령--------------------------------------------------------------------------------비교와 분기를 하나로 합쳐서 한명령으로 할수 있도록 된 루프(loop),스트링(string)LOOP 명령LOOP 명령은 CX레지스터를 뺄셈식 카운터로서 사용하고 ,CX 레지스터가 0 이 될때까지 어떤 문장들을 되풀이 반복한 뒤 지정한 라벨로 분기 하는 명령입니다.즉, CX 에 설정한 횟수만큼 반복을 하기위한 명령인것 입니다.LOOP명령은 오퍼랜드에 분기하는 곳의 라벨을 지정하여, LOOP NEXT와 같은 식으로 사용합니다.이명령은 지금까지 알고 있는 명령을 조합하여 실행하려고하면 DEC CX CMP CX,0 JNE NEXT와 같이 하면 됩니다.즉 , LOOP 명령은 CX 레지스터 뺄셈명령과 비교명령과 조건분기 명령을 한 명령으로 실행하는 명령입니다. 이경우 뺄셈 카운터로서 사용되는 것은 CX레지스터 라고 정해져 있읍니다.루프명령을 실행하면 CX 레지스터 값을 하나 빼고,0 이아니면 지정된 라벨로 분기 합니다.LOOP명령에 의해 CX레지스터에 지정된 횟수만큼 반복할수가 있읍니다.CX 레지스터에는 LOOP명령에서 지정하는 반복범위보다 앞서서 반복하는 횟수를 설정해주지 않으면 안됩니다.예제)LOOP1.ASM1부터 10H까지의 수치를 화면에 출력하는 프로그램CODE SEGMENT ASSUME CS:CODE,DS:CODE;INCLUDE PUTAL2.SUB - INCLUDE화일의 전개부분의 리스트는 생략하였다.;START: PUSH CS -+DS 에 CS의 값을 지정함 POP DX -+; MOV AX,1 MOV CX,10HL1: MOV DS,AL -+ CALL PUTAL

CALL SPACE
이범위를 10H회 반복한다. INC AX
LOOP L1 -+ MOV AH,4CH INT 21H;SPACE PROC NEAR - NEAR지정은 없어도 좋다. PUSH AX -+ 레지스터를 퇴피 PUSH DX -+ MOV DL,' ' -+공백문자를 출력 MOV AH,2
INT 21H -+ POP DX -+퇴피했던 레지스터값을 회복 POP AX -+ RETSPACE ENDP;CODE ENDS END START위의 프로그램은 리스트는 INCLUDE 화일 이 전개된 부분은 생략하고 나타낸것 입니다CX레지스터의 초기 설정은 루프밖에서 세트LOOP명령은 ,그자신 속에 CX의 값을 빼는 명령을 포함하고 있다LOOP : 무조건 지정된 횟수를 반복LOOPE(loop while equal) ,LOOPNE(loop while not equal):어떤 조건이 지정된 횟수 이내에 서 반복을 끝냄이 명령 앞에 비교명령(또는 연산명령)을 놓고 그 결과가 같고 ,또한 CX 레지스터의 1씩을 값을 뺀 결과가 0 이 아니면 반복하는 명령입니다.상한을 CX 회로 설정해 놓고 같지않은 것이 나타날 때까지 반복하는 명령입니다.이것은 데이터의 열중에서 서로 다른 데이터를 찾는데에 사용할수 있읍니다.예제)LOOP2.ASM문자열 "_ _ _ _ _HELLO!" 의 공백의 갯수를 세고,문자열 "HELLO!_ _ _"중의 연속된 문자갯수를 세어 출력한다.CODE SEGMENT ASSUME CS:CODE,DS:DATAINCLUDE PUTAL2.SUB -+INCLUDE화일의 전개부분은 생략한다.INCLUDE CRLF.SUB -+;SPACE EQU ' ';START: MOV AX,DATA MOV DS,AX;;COUNT SPACE LENGTH 공백길이를 센다. MOV CX,10H 상한 회수를 10H회로 결정한다. MOV DL,0 공백수를 DL레지스터에카운트 MOV SI,0 선두번지부터 몇번째인가를 나타내는 SI MOV BX,OFFSET STR1NEXT1: INC DL INC SI SI 가 INC SI 에 의해서 1부터 시작되므로 MOV AL,[BX+SI-1] -- 하나를 빼야한다. CMP AL,SPACE CX내용에서 1을 뺀 결과 0이아닌 동안 여기서 AL과 LOOPE NEXT1 SPACE와 비교한 결과 같으면 NEXT1으로분기한다. DEC DL -----+ 같지않으면 아래로 계속한다. MOV AL,DL --+ +--- 카운트에 더 더한 만큼 뺀다 CALL PUTAL --+------ 표시 CALL CRLF --------- 줄을 바꾼다.;;COUNT STRING LENGTH 문자열겟수를 센다 MOV CX,10H MOV DL,-1 초기값을 -1로 하는것은 MOV SI,-1 0FFFFH세트하는 것NEXT2: INC DL INC SI MOV AL,[BX+SI] CMP AL,SPACE -+ CX를 1감소시켰을 때 0이 아닌범위 내에서 AL와 LOOPNE NEXT2 -+ SPACE가 같지 않으면 NEXT2로 분기하여 문자 갯수 MOV AL,DL 를 센다. CALL PUTAL --- 표시 CALL CRLF 줄을 바꾼다.; MOV AH,4CH INT 21H;CODE ENDSDATA SEGMENTSTR1 DB HELLO!' ;선두가 공백인 문자STR2 DB 'HELLOW! ' ;선두부터 문자가 들어있는 문자DATA ENDS END STARTLOOP 명령과 플레그 레지스터:LOOP 명령, LOOPE명령,LOOPNE명령은 모두 CX 레지스터를 카운터로 하고 한번 실행할때마다 CX 레지스터 값을 하나 씩 값을 빼고 있읍니다.그러나 여기에서 CX 레지스터 값을 뺄떼는 ,결과가 무엇이든 상관없이 플래그 레지스터의 값은 변화하지 않습니다.즉, LOOP명령등의 실행 후 플래그 레지스터의 값은 앞의 연산결과를 유지하고 있읍니다.따라서 LOOP 명령 중의 CX 레지스터를 빼는 명령은 단순한 DEC 명령과 치환할수는없읍니다.(DEC 명령에서는 CF이외의 레지스터가 변화한다.). LOOP명령,LOOPE명령,LOOPNE 명령을 이해를 돕기 위해서 다른 명령으로 치환 한다면 다음과같이 됩니다.LOOP명령 LOOPE명령, LOOPNE명령들의 똑같은 기능을 다른 명령으로 치환+-------------------------------------------------------+
LOOP L1 LOOPE L1 LOOPNE L1



PUSHF PUSHF PUSHF

DEC CX JNZ EXIT JZ EXIT

JE EXIT DEC CX DEC CX

JZ EXIT JZ EXIT

POPF POPF POPF

JMP L1 JMP L1 JMP L1

EXIT:POPF EXIT:POPF EXIT:POPF
+-------------------------------------------------------+여기서 PUSHF 는 플래그 레지스터(flag register)를 스택에 퇴피시킵니다.8.2 스트링(string) 명령--------------------------------------------------------------------------------연속한 데이터를 전송하는 명령(5종류)문자열과 같은 연속한 데이터를 전송하는 명령입니다.리피트 프리픽스(repeat prefix) 명령과 조합하여 사용함으로써 ,한명령으로 대량의 데이터를 전송할수 있는 이점이 있읍니다. 스트링 명령+-----------+-------+-------------------+-------+------------------------+


바이트 단위

워드 단위
+-----------+-------+-------------------+-------+------------------------+
전송 명령군
LODSB
메모리 ->AL
LODSW
메모리 -> AX


STOSB
AL ->메모리
STOSW
AX -> 메모리


MOVSB
메모리 ->메모리
MOVSW
메모리 -> 메모리
+-----------+-------+-------------------+-------+------------------------+
비교 명령군
SCASB
메모리 AL의 비교
SCASW
메모리와 AX의 비교


CMPSB
메모리끼리의 비교
CMPSW
메모리와 메모리의 비교
+-----------+-------+-------------------+-------+------------------------+리피트 프리픽스 명령+-------------+-------+--------------------------------------------------------+
전송 명령군
REP
CX 레지스터에 주어진 횟만큼,다음의 스트링 명령을 반복
+-------------+-------+--------------------------------------------------------+
비교 명령군
REPE
비교결과가 0 및 CX레지스터에 주어진 횟수 이내이면 다


REPZ
음의 스트링 명령을 반복한다.

+-------+--------------------------------------------------------+

PEPNE
비교결과가 0이 아니고 CX레지스터에 주어진 횟수 이내이


PEPNZ
내 이면 다음의 스트링 명령을 반복한다.
+-------------+-------+--------------------------------------------------------+스트링 명령에서는 메모리의 번지를 지정하는 방법이정해져 있고,또한 데이터를 읽는 방법과 쓰는 방법이 차이가 있읍니다.*.데이터를 읽어낼때...DS 내의 [SI]로 표시되는 번지의 내용을 읽어낸다.*.데이터를 써넣을때...ES 내의 [DI]로 표시되는 번지의 데이터를 써넣는다.+----------+
DS:[SI] +-----+ LODS명령+----------+ \
/ +-----------------+MOVS명령
AX 혹은 AL
(CMP명령) +-----------------+
+----------+
STOS명령
ES:[DI] +<----+ ( SCAS 명령)+----------+사용하는 번지도 바이트 단위면 AL, 워드 단위이면 AX 로정해져 있읍니다.따라서 스트링 명령을 사용하기 전에는 필요한 레지스터(DS,ES,SI,DI,CX)의 초기설정을 하지않으면 안되는 대신에,명령자체는 오퍼랜드를 가지지 않고 단순히LODSBMOVSW와 같은 식으로 단순하게 사용할수가 있읍니다.단,스트링 명령은 전송이나 비교 등을 행한 다음,번지지정에 사용되어 SI혹은 DI레지스터의 값을 자동적으로 1(바이트 단위일때) 또는 2(워드 단위일때) 만큼 증가시킵니다. 이것은 다음번지의 데이터를 전송 또는 비교하기위한 준비이고,스트링 명령을 연속하여 사용 함으로써 연속된 번지에 놓여진 데이터를 전송 또는 비교할수있읍니다.(디렉션 플레그값이 1 일때는 ,SI, DI 갑은 감소 된다.)LOOP 명령을 사용하기 위해,편의상 미리 CX 에 문자열의 길이를 넣어두지 않으면 안됩니다. 문자열의 길이를 계산하기위하여 원하는 문자열의 다음에 더미(dummy) 변수 MSG2를 놓아서 두 개의 오프셋 번지의 차를 취합니다.OFFSET MSG2-OFFSET MSG이와 같이 매크로 어셈블에서는 번지등의 덧셈 뺄셈을 소스 프로그램 중에 쓸수가 있읍니다. 이 방법은 정석으로 되어 있읍니다.LOODSB명령은 ,데이터를 전송한다음 SI 값을 하나 증가 시키므로, 한 문자 출력한 다음 LOOP명령으로 돌아와서 다시 LODSB 명령을 실행하게 되면, SI 는 앞에 출력한 문자가 있는 번지의 다음 번지를 나타내고 있읍니다.(연속문자 출력가능)STOS명령메모리로 부터 메모리로 데이터 전송LODS 와 STOS를 조합하는 방법 ,MOVS 를 사용하는 방법,예제)MOVS2.ASMMSG1에들어 있는 스트링 FUNCTION 09H:DISPLAY STRING 을MSG2로 전송하는 펑션 9 를 호출하여 출력한다.CODE SEGMENT ASSUME CS:CODE,DS:DATA,ES:DATA;START: MOV AX,DATA MOV DS,AX MOV ES,AX; MOV CX,OFFSET MSG2-OFFSET MSG1 MOV SI,OFFSET MSG1 MOV DI,OFFSET MSG2 CLD ;DI의 증가 설정NEXT: LODSB ;DS:[SI]로 정해지는 번지메모리 내용을 ES:[DI]로 STOSB ;정해지는 메모리에 전송한다.단,문자열의 길이(CX) 만큼 LOOP NEXT MOV BYTE PTR ES:[DI],'$' MOV DX,OFFSET MSG2 MOV AH,9H INT 21H;CODE ENDSDATA SEGMENTMSG1 DB 'FUNCTION 09H:DISPLAY STRING'MSG2 DB 20H DUP (?)DATA ENDS END STARTLODSB의 실행후 SI의 값이 하나 증가하고,STOSB의 실행후 DI 의 값이 하나 증가,2 개의 명령에 LOOP 명령을 더함으로써 연속한 데이터를 전송할수가 있읍니다.MOVS 명령:위의 LODS 명령과 STOS 명령을 MOVS 명령으로 치환CODE SEGMENT ASSUME CS:CODE,DS:DATA,ES:EXTRA;START: MOV AX,DATA MOV DS,AX ;DS설정 MOV AX,EXTRA ;독립된 ES의 설정이 필요 MOV ES,AX; CLD ;DI의 증가 설정 MOV DX,5 ;5번 되풀이 MOV DI,OFFSET MSG2NEXT2: MOV CX,OFFSET DMSG - OFFSET MSG1 MOV SI,OFFSET MSG1NEXT: MOVSB ;CX의 값이 0이 될때 까지 MSG1번지부터 시작하는 스트링 LOOP NEXT ;을 MSG2 번지위치부터 옮겨 놓는다. DEC DX ;DX 에서 1을 빼라 JNZ NEXT2 ;0 이 아니면 NEXT2로 가라. MOV BYTE PTR ES:[DI],'$' ;메모리에 $(문자열 끝표시)를 넣는다. MOV AX,ES MOV DS,AX ;펑션호출 9번의 앞에는 DS의 설정이 필요 MOV DX,OFFSET MSG2 MOV AH,9H ;DX에 지정된 번지부터 저장된 스트링을 $ 자가 나타 INT 21H ;날때까지 출력하는 시스템 펑션 호출. MOV AH,4CH INT 21H;CODE ENDS;DATA SEGMENTMSG1 DB 'REPEAT SAME MESSAGE 5 TIMES!'DMSG DB ?DATA ENDS;EXTRA DB 100H DUP (?)EXTRA ENDS END START8.3 리피트 프리픽스(1)--------------------------------------------------------------------------------리피트 프리픽스 명령은 스트링 명령과 조합하여 사용하고 ,스트링 명령을 일정 횟수 연속하여 사용 하는것 입니다.REP MOVSB-+-+----->이것이 리피트 프리픽스이다. CX 에 지정된 횟수만큼 MOVSB를 되풀이 하라는 의사명령 리피트 프리픽스는 스트링 명령 앞에 놓고,스트링 명령의 기능 확장을 지정여기서 STOSB -->B는 바이트를 나타냄 STOSW -->W는 워드를 나타냄따라서 AX 에 AB 가 들어 있어도 STOSB는 B 만을 나타낸다.AX 레지스터에 'AB'를 대입하고 있으므로, AL 레지스터의 내용은 'B'=42H가 됩니다.워드단위의 스트링 명령을 사용한 경우에는 20H 개의 바이트 의 데이터가 전송됩니다.이것을 실행하면A>MOVS5BABABABABABABABABABAAX레지스터의 값 'AB' 가 메모리 상에 전송돌 경우에는 역워드(reverse word)형식으로되기 때문에 ,'BA' 순서로 되어버린 점에 주의 하십시요.REP 명령은 조합하는 스트링 명령이 바이트 형인가 워드 형인가에 따라서 전송되는 바이트 수는 달라집니다.예를들면 20H 바이트의 데이터를 전송할때에 MOVSB명령을 사용ㄹ한다고 하면 CX 레지스터의 초기치를 20H로 ,MOVSW명령을 사용한다고 하면 CX 레지스터의 초기치를 10H로하지 않으면 안될것입니다.전송하는 데이터의 수가 홀수 바이트 일때에는 워드형의 스트링명령을 사용하면 마지막 데이터가 전송되니 않는다든지 ,여분의 데이터 까지 전송 된다든지 하는 일이 있으므로 주의가 필요합니다. 미리 데이터수를 알과있는 경우는 괜찬지만 경우에따라 전송하는 데이터수가 변화 할때에는 바이트 형의 스트링 명령을 사용하는 쪽이 안전 합니다.8.4 비교명령군의 사용법--------------------------------------------------------------------------------메모리와 레지스터의 값을 비교하는 SCAS명령,메모리끼리의 값을 비교하는 CMPS명령SCAS명령AL 레지스터의 값과 ES:[DI]에 의해 표시되는 메모리의 내용을 비교몇번 반복했는가를 알기위해서 ,원래의 CX값을 보존해두어,루프에서 빠져나온 후의 CX 값을 빼면 된다.문자열길이의 계산 : STR2 - STR1 OFFSET STR2 - OFFSET STR1과 완전히 같은 역활을 합니다. 이것도 하나의 정석으로서 외워두십시요CODE SEGMENT ASSUME CS:CODE,DS:CODE,ES:CODE;INCLUDE PUTAL2.SUBSTART: MOV AX,CODE ; MOV DS,AX MOV ES,AX ;DS와 ES 의 설정 CLD ;DI 의 증가 설정 MOV AL,'&' ;문자열 중에서 찾는문자 MOV DI,OFFSET STR1 MOV CX,STR2-STR1 ; 문자열의 길이를 계산하려면 PUSH CX ;OFFSET 을 생략해도 좋다.NEXT: SCASB------------+일치하는 문자가 있는가 찾는다. JE FOUND
(AL의값과 ES:[DI]로 지정된 메모리 내용과 내용을 비교한 LOOP NEXT --+ 다,그리고 자동적으로 DI는 증가 CX 는 감소한다.) JMP NOTFOUNDFOUND: DEC DI MOV DX,OFFSET FOUNDMSG1 MOV AH,9 INT 21H MOV AX,DI --+- 발견한 번지를 표시 MOV AL,AH
CALL PUTAL
MOV AX,DI
CALL PUTAL --+ MOV DX,OFFSET FOUNDMSG2 MOV AH,9 INT 21H POP AX --+문자열의 길이-뺄셈 카운터에 의해 몇번째 문자에서 SUB AX,CX
발견되었는지를 계산하여 표시 CALL PUTAL --+ JMP EXITPNOTFOUND: MOV DX,OFFSET NOTFOUNDMSG MOV AH,9 INT 21HEXITP: MOV AH,4CH INT 21H;FOUNDMSG1 DB 'FOUND ADDRESS = $'FOUNDMSG2 DB 'H COUND = $'NOTFOUNDMSG DB 'NOT FOUND $'STR1 DB 'ABCDEFG&ABC'STR2 DB ?CODE ENDS END STRATCMPS 명령 :2개의 데이터열이 같은가 다른가를 비교하는데 사용합니다.DS:[SI]가 지정하는 메모리 한 바이트 내용과ES:[DI]가 지정하는 메모리 한 바이트 내용을 비교하는 명령이다.CMPSB명령을 하면 SI,DI의값이 자동적으로 하나만큼 증가 한다는 점입니다.예제)CMPS2.ASM메모리 번지 CMP-STRING 부터 저장되어 있는 "ABC" 문자와 키보드로 부터 입력하여메모리 번지 BUFF부터 저장된 문자 스트링 속에 같은 "ABC" 가 몇 번째 글자부터 있는가 알아 낸다.CODE SEGMENT ASSUME CS:CODE,DS:CODE,ES:CODE;INCLUDE CRLF.SUBINCLUDE PUTAL2.SUBSTART: MOV AX,CS MOV DS,AX MOV ES,AX CLD MOV DX,OFFSET OPENING_MSG CALL DISP CALL CRLF MOV DX,OFFSET MAX_CHARS -+리터키가 눌릴때까지 키보드로부터 입력된 MOV AH,0AH
스트링을 연속적으로 BUFF속에 저장하고 총 INT 21H -+입력된 문자갯수를 CHARS-ENTERED에 지정하 CALL CRLF 는 시스템 펑션 A 번이다. MOV CH,0 MOV CL,CHARS_ENTERED MOV BP,OFFSET BUFF DEC BP INC CXNEXT: DEC CX CMP CX,3 JB NOTFOUND INC BP MOV DI,BP MOV SI,OFFSET CMP_STRINGS CMPSB <---+DS:[SI]로 지정되는 메모리내용과 ES:[DI] 로 지정되는 JNE NEXT
메모리 내용을 비교한다.비교한후,자동적으로 DI,SI값 CMPSB <---+을 증가시켜 다음것을 비교한다. JNE NEXT
CMPSB <---+ JNE NEXT MOV DX,OFFSET FOUND_MSG1 CALL DISP -+몇번째 문자에서 발견되었는지를계산표시 MOV AL,CHARS_ENTERED
SUB AL,CL -+ CALL PUTAL JMP EXITPNOTFOUND: MOV DX,OFFSET NOTFOUND_MSG CALL DISPEXITP: MOV AH,4CH INT 21HDISP PROC MOV AH,09H INT 21H RETDISP ENDPOPENING_MSG DB 'INPUP STRINGS INCLUDE' $'FOUND_MSG1 DB 'FOUND CHARACTERS AT $'NOTFOUND_MSG DB 'NOT FOUND $'MAX_CHARS DB 80CHARS_ENTERED DB ?BUFF DB 80H DUP (0) +-->최대 입력가능 문자 갯수(CR포함):1바이트+--+---------+---------+----------------------+


버퍼 --+-->입력된 실지 문자가 들어가는곳+------------+--+------+----------------------+ +---->실제로 입력된 문자갯수(CR포함하지 않음) : 1바이트CMP_STRINGS DB 'ABC'------>비교대상이되는 문자열CODE ENDS END START위문제는 상당히 논리가 어려운 문제입니다.그러나 꾸준히 추적해나가면 곧 이해할수있을 것입니다.그러나 이 프로그램을 완전히 이해했다면 어셈블리 언어의 상당한 수준을 파악하게 된셈이며 앞으로 어떤 복잡한 어셈블리 언어 프로그램도 이해 할수있는 능력이 생긴 것입니다.

asm] 어셈러브 강좌 펌 5


제 6장 비교분기와 서브루틴--------------------------------------------------------------------------------디버그(DEBUG)의 커맨드의 요약-------------+----------------------------------------+-------------------------커맨드
목적(Purpose)
명령COMMAND

형식(Format)-------------+----------------------------------------+-------------------------Assemble
문장을 어셈블한다. A[번지]Compare
메모리를 비교한다. C범위번지Dump
메모리를 표시한다. D[번지]이거나
D[범위]Enter
메모리를 변경한다. E 번지 [리스트]Fill
메모리 블럭을 변경한다. F범위 리스트Go
선택적 브레이크 포인트를 갖고 실행한다. G [=번지]
[번지
[번지...]]Hexarithmetic
16진수덧셈,뺄셈 H 값 값Input
입력 바이트를 읽거나 표시한다. I 포트번지Load
화일이나 절대 디스켓 섹터를 메모리에 로드한다. L[번지[드라이브
섹터 섹터]]Move
메모리 블럭을 전송한다. M 범위번지Name
화일이나 패러미터를 정의한다. [d:]
[패스]화일이름[.확장자]Output
출력바이트를 내보낸다. O 포트번지 바이트Quit
디버그 프로그램을 끝낸다. QRegister
레지스터나 플레그를 표시한다. R[레지스터이름]Search
문자를 찾는다. S 범위리스트Trace
집행하고 표시한다. T [=번지][값]Unassemble
명령을 디어셈블한다. U[번지]이거나
U[범위]Write
화일이나 절대 디스켓 섹터를 기록한다. W[번지][드라이브
섹터 섹터]-------------+------------------------------------------------------------------6.1 반복처리와 조건분기 명령(conditional branch instruction)--------------------------------------------------------------------------------조건분기 명령:반복을 할때 필요 불가결한 요소CMP AX,0 ; AX레지스터의 값을 0 과 비교하라JE 100 ; 바로 위의 비교 결과가 같다면 100번지로 분기하라CMP(compare) : 레지스터나 메모리 및 숫자의 크기를 비교합니다.JE(Jump if Equal) 같다면 분기하라JNE(Jump if Nor Equal) 같지 않다면 분기하라JA(Jump if Above) ~ 이상 이라면 분기하라JC(Jump if Carry) 캐리플래그가 1 이라면 분기하라CMP +- 범용 레지스터(8/16비트)-+ +-레지스터(8/16비트) +- 메모리 (8/16비트)-+ +-메모리 (8/16비트) +-숫자 (8/16비트)예제) JMP1.ASM1부터 100 까지 의 수를 더하는 프로그램CODE SEGMENT ASSUME CS:CODE,DS:CODE MOV AX,CODE ; DS설정 MOV DS,AX; MOV CX,100 ;CX에 100을 지정 MOV AX,0 ;AX 에 0을 지정MEXT: ADD AX,CX SUB CX,1 CMP CX,0 ; CX의 내용이 0인가 비교 JNE NEXT ;0이면 밑으로 아니면 NEXT 라는 라벨로 이동 MOV TOTAL,AX MOV AH,4CH ;끝내고 MS-DOS로 돌아간다. INT 21H;TOTAL DW ?;CODE ENDS END라벨(label)의 사용:라벨이라는 것은 명령등이 있는 번지에 붙여진 이름입니다.라벨이름의 직후에 콜론" : " 을 넣는다INC,DEC 명령:레지스터나 메모리의 내용을 +/-1 하기위한 명령으로서 INC(increment.증가)DEC(decrement.감소)명령이 준비되어 있읍니다. SUB CX,1대신 DEC CX 로 쓸수가 있읍니다.INC +- 범용 레지스터(8/16비트) +- 메모리 (8/16비트)DEC +- 범용 레지스터(8/16비트) +- 메모리 (8/16비트)또한 여산 직후에 그결과가 0 인지 아닌지를 비교하여 분기하는 경우에는 비교명령을 생략 할수가 있읍니다. 플레그 레지스터의 동작에 관한 절에서 설명하겠지만 ,ADD나SUB,INC,DEC 등의 연산 명령 다음에 는 직접 조건 분기 명령을 넣을 수가 있읍니다.( 이 경우 에 는 결과가 0 으로 비교된 것으로 간주 됩니다.)따라서NEXT: ADD AX,CX DEC CX CMP CX,0 JNE NEXT는NEXT: ADD AX,CX DEC CX JNE NEXT가 됩니다.반복을 끝내는 조건은 ,처음의 하나 ,마지막의 하나에 주의L1: ADD AX,CX INC CX CMP CX,100 JBECX=100 으로 해버린면 AX 에는 100 이 더해지지 않읍니다.그래서 반복하는 조건으로 CX < 100 의 사이에서가 아니라 CX<=100의 조건분기 명령에는 JBE(Jump if Below or Equal)를 사용합니다.DUP의사명령과 블럭전송:---------------------- DB 16 DUP (?)
+--->DUP는 duplication 의 약자여기에서 행한 정의 중에 사용되고 있는 DUP는 ()속에 것을 ()왼쪽의 갯수만큼 반복하라는 의미입니다.예제)JMP3.ASMMSG1부터 저장된 10바이트를 MSG2 로 전송하는 프로그램CODE SEGMENT ASSUME CS:CODE,DS:DATA; MOV AX,DATA ; DS설정 MOV DS,AX MOV SI,OFFSET MSG1 ;SI 에 MSG1 번지값을 지정한다. MOV DI,OFFSET MSG2 MOV CX,10CONT: MOV AL,BYTE PTR [SI] ;MSG1 부터 MSG2 로 1바이트전송 MOV BYTE PTR [DI],AL INC SI ;전송하는 번지를 하나씩 증가시킨다. INC DI DEC CX ;전송해야할 갯수의 카운트를 하나씩 줄인다. JNE CONT MOV AH,4CH ; 끝내는 시스템호출 INT 21H;CODE ENDS;----------------DATA SEGMENTMSG1 DB 'ABCDEFGHIJKLMNOP'MSG2 DB 16 DUP (?) ;16바이트 만큼의 비초기화 메모리를 확보DATA ENDS END데이터 세그먼트(DS;data segment)값을 아는 방법:위프로그램의 실행결과를 확인하려면 ,MSG1 및 MSG2 에 있는 번지를 알지않으면 안됩니다. 그러나 프로그램을 실행하기전에는 DS 의 값은 PSP(program segment prefix)의 선두를 가리키고 있기 때문에 데이터를 읽을 수가 없읍니다. +--------------------------------------------------+DS:데이터 세그먼트
+---------------+--->DS,ES
레지스터

PSP

ES:엑스트라 세그먼트
+---------------+--->CS,SS
레지스터

코드 세그먼트


+---------------+<-- 여기에 세그먼트 번지를


데이터 세그먼트
알고싶다

+---------------+
+--------------------------------------------------+ 메모리에 로드되었을 때의 EXE화일의 예실제로 데이터가 저장되어 있는 세그먼트 번지를 알필요가 있읍니다.MOV AX,DATAMOV DS,AX 에서 DATA 의 내용을 대치하는MOV AX,2244 로 역어셈블 됩니다. 2244는 각 PC 의 상황에따라 다릅니다.-D2244:0,1F2244:0000 41 42 43 44 45 46 47 48-49 4A 4B 4C 4D 4E 4F 50 ABCDEFGHIJKLMNOP레지스터 읽는 R 커맨드에 의해 데이터 세그먼트의값을 세트한다음,다음과 같이 볼수도있읍니다.-RDSDS 2232:2244-D0,1F2244:0000 41 42 43 44 45 46 47 48-49 4A 4B 4C 4D 4F 50조건 분기 명령에 대한 일람표를 만들었읍니다.+-----------------+----------------+---------------------+
분기하기위한 A,B
부호없는 숫자인
부호있는 숫자인

의 대소관계
경우
경우
+-----------------+----------------+---------------------+
A>B
JA/JNBE
JG/JNLE

A>=B
JNB/JAE
JGE/JNL

A=B
JZ/JE
JZ/JE

A<=B
JBE/JNA
JLE/JNG

A
JB/JNAE
JL/JNGE

A=\=B
JNZ/JNE
JNZ/JNE
+-----------------+----------------+---------------------+6.2 무조건 분기명령--------------------------------------------------------------------------------JMP 명령:예제)JMP4.ASMMSG1번지부터 시작하는 문자열을 MSG2번지 이후로 옮기는데 " $" 자가나타날때까지 행하는 프로그램CODE SEGMENT ASSUME CS:CODE,DS:DATA; MOV AX,DATA ;DS 설정 MOV DS,AX MOV SI,OFFSET MSG1 ;MSG1번지를SI에 지정 MOV DI,OFFSET MSG2 MOV DX,0CONT: MOV AL,BYTE PTR [SI]
CMP AL,"$" ;'$' 이면 종료
JE EXITP
MOV BYTE PTR [DI]
INC SI
INC DI
INC DX ;전송문자수의 카운트+--- JMP CONT ;무조건 반복EXITP: MOV NUMBER,DX MOV AH,4CH INT 21H;CODE ENDS;-------------------DATA SEGMENTMSG1 DB 'ABCDEFGHIJKLMNO'MSG2 DB 16 DUP (?)NUMBER DW ?DATA ENDS END종료를 나타내는 문자 (여기서는 "$" 자 )가 나타날때 까지 전송을 반복한다.대문자 - 소문자 변환 루틴:영어대문자는 41H(=A)부터 5AH(=Z) 까지 연속적으로 할당되어있읍니다.CODE SEGMENT ASSUME CS:CODEMEXT: MOV AH,1 ; 1문자입력 시스템 호출명령사용 INT 21H CMP AL,1AH ; CTRL+Z 이면 종료 JE EXITP CMP AL,'A' ; 아스키코드 'A' 미만이면 L1 으로 JB L1 CMP AL,'Z' ; 아스키코드 'Z' 보다크면 L1 으로 JA L1 ADD AL,'a'-'A' ;상응하는 소문자를 찾기위해'a'-'A'=20H를 더한다.L1: MOV AH,2 ; 1문자 출력 시스템 호출 명령사용 MOV DL,AL INT 21H JMP NEXTEXITP: MOV AH,4CH INT 21HCODE ENDS END6.3 비교분기와 플레그 레지스터--------------------------------------------------------------------------------조건분기명령은 비교명령이나 연산명령의 결과 에 의해 세트된 플레그 레지스터의 값에 따라서 분기할것인지 아닌지를 결정하고 있는 것입니다.플레그 레지스터의 각 비트의 의미플레그 레지스터는 이와 같이 일반적인 레지스터와 달라서 ,여러가지 상태를 기억하기의한 레지스터입니다.비트마다 독립된 의미를 가지고있어 독립되어 작동한다.CF:캐리 플레그연산한 결과,최상의 비트로부터의 높은 자리로 자리올림(캐리 CARRY) 혹은 최상의 비트로부터의 빌림(borrow)이 발생한 경우에 1로 세트되고 그 이외의 경우 0 으로 리셋된다. 그밖의 목적으로 사용될때도 있다.PF:패리티 플레그연산한 결과 ,1 로 된 비트의 수가 짝수개(even number)일 때 1로 세트되 고,홀수(odd number)일때 0 으로 리셋된다.AF:보조 캐리 플레그8(16)비트 연산에서 ,하위 4(8)비트로 부터 상위 4(8)비트로 자리올림 혹은 빌림이 발생한 경우에 1로 세트되고 그이외의 경우 0 으로 리셋된다. 10 진 보정명령에 있어서도 사용된다.ZF:제로 플레그연산한 결과 가 0 으로 되었을 때에 1로 세트되고,그 이외일때에 0 으로 리셋된다.SF: 사인 플레그연산한 결과,최상의 비트가 1 이 되었을 때 (즉 ,보수표현으로 음수가 되었을 때)1로 세트되고,그 이외일때에 0 으로 리셋된다.OF:오버플로우 플레그(overflow flag)연산을 부호가 달린 숫자로 했을 때 ,오버플로우 혹은 언더 플로우(under flow)가 발생한 경우에 1로 세트되고,그이외 일때에는 0 으로 리셋된다.이상의 6가지플레그는 연산의 결과에 따라서 세트 혹은 리셋되는 플레그로써 스테이터스 플레그(status flag, 상태 플레그)라고 부릅니다.플레그에는 그 이외에도 3가지더 있어서 ,그들은 CPU 의 동작 상태를 제어하는 것으로서 컨트롤 플레그(control flag,제어 플레그)라고 부릅니다.DF:디렉션 플레그(direction flag)스트링 조작을 할때에 이 플레그가 0 이면 번지를 나타내는 레지스터 값이 자동적으 로 증가하고 1 이면 레지스터값은 자동적으로 감소한다.IF:인터럽트 플레그(interrupt . enable . flag)이 플레그가 0일 때 INTR 단자로 부터의 외부 인터럽트요구는 무시되고 ,1일때에는외부 인터럽트 요구를 받아들일수 있게 된다.TF:트랩 플레그(trap flag)이 플레그가 0 일때 CUP 는 보통대로 명령을 실행한다.이 플레그가 1 일때 CUP 는 한 명령 시행할때 마다 자동적으로 내부 인터럽트(INT1)를 발생하고 ,인터럽트처리 루틴으로 들어간다.(단,이 처리 루틴의 실행중에는 트랩플래그는 0 으로클리어된다.) 프로그램의 추적(trace)에 사용된다.캐리 플레그는 프로그램에 의해서도 세트 혹은 리세트 할 수 있습니다.플레그 레지스터 제어명령STC(Set Carry flag) 캐리플레그를 1로 세트한다.CLC(CLdar Carry flag) 캐리 플레그를 0으로 리셋한다.CMC(CoMplement Carry flag) 캐리 플레그가 0이면 1로 ,1이면 0으로 세트한다.STD(Set Direction flag) 디렉션 플레그를 1로 세트한다.(번지를 자동적으로 감소시키는 방향)CLD(CLear Direction flag) 디렉션 플레그를 0 으로 리셋한다.(번지를 자동적으 로 증가시티는 방향)STI(Set Interrupt-enable flag) 인터럽트 플레그를 1 로 세트하고 인터럽트를 받아 들일수 있는 상태로 한다.CLI(CLear Interrupt-enable flag)인터럽트 플레그를 0으로하고,인터럽트를 걸지 못하 게 금지상태로 한다.LAHF(Load AH from Flags) 플래그 레지스터의 하위 8비트를 AH레지스터로전송한 다.사용하지 않는 비트의 값은 정해져 있지않다.SAHF(Store AH into Flags) AH레지스터의 내용을 플래그 레지스터의 하위 8비트 에 전송한다.PUSHF(PUSH Flags onto stack) 플레그 레지스터의 내용을 스택(stag)상에 푸쉬(PUSH) 한다.POPF(POP Flags off stack) 스텍위의 워드 데이터를 플레그 레지스터에 POP 한다.비교연산 명령과 조건분기명령의 관계:비교연산 명령은 뺄셈명령과 같은 것입니다.다른점은 비교한 결과 비교를 행한 레지스터나 메모리의 내용은 전혀 변하지 않고 단지 플레그 레지스터만을 변화시킨다.CMP AX,BX라고 했을때,AX 레지스터로 부터 BX 레지스터의 내용을 (가상적으로 ) 뺀다음,그 결과에 따라서 플레그 레지스터 만을 변화 시키고 AX,BX 의 내용은 보존 됩니다.SUB AX,BX라고 하면 플레그 레지스터는 완전히 똑같게 세트되지만,AX 레지스터의 값도 변화되어 AX 에서 BX 를 뺀 결과가 AX 의 값이 되어 버립니다.플레그레지스터의 값은 산술 논리연산을 행할 때에 세트 리셋되고, 전송명령이나 분기명령을 실행해서는 변화하지 않습니다.조건 분기 명령의 정리+--------+---------+---------------+--------+---------------+
A,B 의
부호없는
조건을 만족하는
부호있는
조건을 만족하는

대소 관
숫자의
플레그의 상태
숫자의
플레그의 상태

계
경우
CF
경 우
SFⓧOF
ZF
+--------+---------+-------+-------+--------+-------+-------+
A>B
JA/JNBE
0
0
JG/JNLE
0
0

A>=B
JNB/JAE
0
*
JGE/JNL
0
*

A=B
JZ/JE
*
1
JZ/JE
*
1

A<=B
JBE/JNA
1
1
JLE/JNG
1
1

A
JB/JNAE
1
*
JL/JNGE
1
*

A=\=B
JNZ/JNE
*
0
JNZ/JNE
*
0
+--------+---------+-------+-------+--------+-------+-------+A,B 의 대소관계는 ,CMP A,B 즉(A-B)의 결과로 표시된다.ⓧ는 배타적 논이합(exclusive OR)을 구하는 연산이다.* 표시란의 값은 0 이라도 1 이라도 조건판단에 영향을 주지 않는다.JA/JNBE 와 같이 / 로 구분된 2개의 표현은 ,완전히 같은 관계를 다른 말로 표현한것으로서 ,어느쪽을 사용해도 상관이 없다.단,디버그에 의한 디스어셈블 결과는 왼쪽의 표현 으로 된다.조건 분기명령에서는 쇼트 점프(short jump) 즉,명령이 있는 다음 번지로 부터 +127 ~-128바이트 이내로 만 분기할수있다.+------+------------+------------+------------------------------------------+
플레그
1일때의 분기
0일때의 분기
플레그가 1일때의 의미
+------+------------+------------+------------------------------------------+
SF
JS
JNS
보수표현으로 음수이다.

ZF
JZ/JE
JNZ/JNE
결과가 0 이다.(위표의 A=B와 같다)

PF
JP/JPE
JNP/JAE
1이된 비트의 수가 짝수이다.

CF
JB/JNAE
JNB/JAE
캐리플레그가 1이다(연산한결과 자리올림




혹은 빌림이 발생한 경우 등)

OF
JO
JNO
보수표현을 사용한 연산에서 결과가 범위를




초과했다.
+------+------------+------------+------------------------------------------+
레지스터

명령의 의미
+------+------------+------------+------------------------------------------+
CX
------
JCXZ
CX레지스터가 0일때만 분기한다.
+------+------------+------------+------------------------------------------+조건분기명령 약자를 읽는법A:Above 위(부호없음) O:Overflow 오버플로우B:Below 아래(부호없음) Odd 짝수E:Equal 0 혹은 같음 P:Parity 패리티G:Greater 위(부호있음) S:Sign 부호가 음수L:Less 아래(보호있음) Z:Zero 0 혹은 같음N:Not ~ 가아니다JNGE 는Jump if Not Greater or Equal이므로(A>=B),즉 A
플레그 이름
OF
DF
IF
SF
ZF
AF
PF
CF
+-----------+---+---+---+---+---+---+---+---+
0
NV
UP
DI
PL
NZ
NA
PO
NC
+-----------+---+---+---+---+---+---+---+---+
1
OV
DN
EI
NG
ZR
AC
PE
CY
+-----------+---+---+---+---+---+---+---+---++--------------------+--------------------+-----------------+
플레그 이름
0
1
+--------------------+--------------------+-----------------+
Overflow flag
Not oVerflow
OVerflow

Direction flag
UP
DowN

Interrupt flag
Disable Interrupt
Enable Interrrupt

Sign flag
PLus
NeGative

Zero flag
Not Auxiliary carry
ZeRo

Auxiliary Carry flag
Parity Odd
Auxiliary Carry

Parity flag
Parity Odd
Parity Even

Carry flag
Not Carry
Carry
+--------------------+--------------------+-----------------+MOV BX,8888HCMP BX,00과 비교한결과 8888H - 0H의 결과에 따라서 플래그 레지스터가 세트됩니다.뺄셈의 결과 는 8888H 이므로 최상위 비트가 1 이 되고 ,사인 플래그는 NG(음수)가됩니다.그러나 빌림은 발생하지 않았으므로 ,캐리 플래그는 NC (0)가 되어 있읍니다.오버플로우 플래그가 NV(0)입니다.따라서 부호없는 비교 JB 는 조건을 만족하지 않으므로,다음 명령으로 진행합니다.여기에서 부호있는 비교 JL은 조건을 만족하고 있으므로 ,지정한 번지로 분기 합니다.주의 )1을 더하는 명령을 ADD명령으로 한경우와 ,INC 명령으로 한 경우덧셈결과는 양쪽다 같지만 플래그 레지스터의 변화는 달라 집니다.보통의 산술연산 명령에서는 자리 올림 혹은 빌림이 발생한 경우는 캐리 플래그가 세트 되지만 ,INC 명령과 DEC 명령만은 특수해서,이 2 종류의 명령만은 자리올림이나 빌림이 발생해도 캐리 플래그에 영향을 주지 않습니다.이때문에 자리올림()을 사용하여 조건판단을 하는 명령앞에 INC 명령,DEC 명령을 놓을때 는 주의 가 필요 합니다. 캐리 플래그는 ,이들명령보다 앞의 상태를 계속 가지고 있읍니다.INC ,DEC 명령이 이와 같은 성질을 갖고있다는 것은 결코 불편한것이 아니라 ,오히려 실제 프로그램 상에서 느 도움이 되는 경우가 많읍니다.캐리 플래그를 제외한 다른 플래그 레지스터는 INC,DEC 명령의 결과에 따라서 세트 혹은 리셋됩니다.6.4 서브루틴의 사용법--------------------------------------------------------------------------------서브루틴(subroutine)이란프로그램 중에서 여러번 되풀이 사용되는 부분을 메인 루틴으로 부터 독립하여 작성프로그램을 효율적으로 하는 효과가있다.프로그램을 처리내용에 따라 불럭으로 나눔으로써 전체를 보기 쉽도록 해주고 ,보수를 쉽게 만들어 주는 이점이 있읍니다.어셈블러의 서브루틴은 BASIC 과 비숫한 사용방법이다.서브루틴의 끝을 나타내는 RET 명령으로 끝납니다.RET (return command )는 서브루딘으로 부터 메인 루틴으로 돌아오는 명령입니다.서브루틴을 부를 때는 CALL 다음에 서브루틴의 시작에 붙여진 라벨을 사용합니다.예)CALL1.ASM0부터 9까지의 숫자를 출력하는 프로그램이다. 단 한 자 한자 출력하는 서브루틴을 만들어 호출한다.CODE SEGMENT ASSUME CS:CODE; MOV CX,0NEXT: CALL SUB1 ;CALL명령으로 서브루틴을 호출 INC CX CMP CX,10 JB NEXT MOV AH,4CH INT 21H;SUB1: MOV DX,CX ADD DL,'0' MOV AH,2 INT 21H RET ;리턴명령CODE ENDS END서브루틴 SUB1속에서는 , CX 레지스터의 값을 변경시키지 않도록 CX 레지스터의 값을DX 레지스터로 전송한다16진수값의 화면상에 출력법:기본구상 _ AL레지스터의 내용을 표시하려고 한다면, AL=3FH일경우"3" 와 "F" 와의 2가지 문자를 출력하지 않으면 안된다.AL레지스터의 내용을 상위 4비트와 하위 4비트로 나누어서 ,2번에 걸쳐 출력해야 한다.+--------------------------------------------------------+
AL DL

+--+--+ +--+--+


3
F
--->
0
F
--->아스키 코드로 변환 --> 출력

+--+--+ +--+--+

DL


+--+--+

+------->
0
3
--->아스키 코드로 변환 --> 출력

+--+--+
+--------------------------------------------------------+레지스터의 비트 단위로 데이터를 취급하려면,보통 논리 연산명령이나,쉬프트(이동)로테이트(rotate, 회전 ) 명령을 사용한다.여기서는 학습을 위해 곱셈과 나눗셈을 사용한다. AL 3F \/ * 10H AX 03F0 /
상위자리 보존 <--- 03
AH 00
\ \/ AX 00F0 \/ %10H AX 000F \/ <-------- 0F예제)PUTAL.ASMAL레지스터 내의 값을 ASCII코드 16진수값으로 화면에 표시하는 프로그램(서브루틴을 사용한다.)AL 내의 값은 3FH값을 예로 들었다.CODE SEGMENT ASSUME CS:CODE,DS:CODE; MOV AX,CODE ; DS의 초기치 설정 MOV DS,AX; MOV AL,3FH ;처음AL에 3FH가 들어 있다고 하자 CALL PUTAL ;서브루틴을 호출한다.; MOV AH,4CH INT 21H;-----------------------PUTAL: MOV BL,10H ;AL을 10H 하면 AH,AL -----+상위자리 MUL BL ; 03 F0 가 된다.
하위자리로 MOV LEVEL2,AH ;
분할하는 MOV AH,0 ;AX를 10H 분의 1 로 나누면 AH AL
서브루틴 MOV BL,10H 00 0F 가 된다
DIV BL
MOV LEVEL1,AL ; 하위자리 보존
MOV DL,LEVEL2 ; -+ 상위자리 표시
CALL PUTHEX -+
MOV DL,LEVEL1 ; -+ 하위자리 표시
CALL PUTHEX -+
RET ----+;---------------------------PUTHEX: CMP DL,0AH JAE HEX2 ADD DL,'0' ; 0 의 ASCII 코드 값이 30H 이다. ----+수치에 대한 JMP HEX3 (0 에서 9 인경우)
아스키 코드를HEX2: ADD DL,'A'-0AH ; A 에서 F 인경우
산출,표시하는HEX3: MOV AH,2 'A' 의 ASCII코드값은 41이다
서브루틴 INT 21H 'B'는 42가 표시도기 위해서는
RET 41+1이 되어야 하는데 이것은
'A'+(BH-AH)의 계산으로 가능하다. --+LEVEL2 DB ?LEVEL1 DB ?;CODE ENDS END서브루틴 PUTAL 속에서 다시 서브루틴 PUTHEX 를 호출할수도 있읍니다.여기에서 출력시스템 INT 21은 DL 레지스터에 ASCII코드값을 넣을 때 그에 해당하는ASCII 문자가 화면에 출력된다.0 에서 9 까지의 숫자에 대응하는 아스키 코드와 A 에서 F 까지 대응 하는 아스키코드가 연속하여 있지안으므로 ,숫자가 0AH 미만인지 아닌지 에 따라 변환을 위해서 더하는 숫자가 달라 집니다.+-------------+--------------+--------------+
문자
0 ~ 9
A ~ F

아스키 코드
30 ~ 39
41 ~ 46
+-------------+--------------+--------------+숫자를 표시할경우에는 윗자리를 먼저, 아랫자리를 나중에 표시하지 않으면 안 됩니다. 구한 순서와 표시한 순서가 일치하지 않을 때도 있으므로 ,그 와 같은 경우에는각 자리의 숫자를 보존해 두는 것이 필요합니다.PROC에 의하 서브루틴의 구조화:서브루틴을 보다 구조적으로 표현하기위해서 프로시듀어(procedure)의사 명령에 의해 서브루틴의 앞뒤를 명시 하도록 합니다.SUB1 PROC 서브루틴 본체SUB1 ENDP16진수값의 입력법예제)GETAL.ASM키보드로 부터 ASCII코드를 입력하여 이코드에 해당하는 ASCII문자 출력CODE SEGMENT ASSUME CS:CODECR EQU 0DHLF EQU 0AH;NEXT: CALL GETAL ; 키보드로 부터 두개의 숫자 입력 JC EXITP ;에러이면 끝냄 MOV DL.AL CALL PUTASC ;아스키 코드의 출력 JMP NEXTEXITP: MOV AH,4CH ;종료하여 MS-DOS로돌아간다. INT 21H;-----------------------GETAL PROC MOV AH,1 ; 우선한자를 입력한다. INT 21H CALL CVTAL ; 아스키 코드 ---> 숫자 JC GETEND ;에러이면 되돌아 간다. MOV DH,AL ; 보존 MOV AH,1 ;두번째글자입력 INT 21H CALL CVTAL --- 아스키 코드 ---> 숫자 JC GETEND ;에러이면 되돌아간다. MOV DL,AL MOV BH,10H ;상위자리를 10배 MOV AL,DH MUL BH ADD AL,DL ;하위자리와 더한다GETEND: RETGETAL ENDP;--------------------------CVTAL PROC CMP AL,'0' JB ERR1 ;ASCII 코드값으로부터 CMP AL,'9' 30H보다 적을경우 ERR1 JA SKIP1 SUB AL,'0' JMP SKIP2SKIP1: CMP AL,'A' ---+ 'A'~'F'이면 JB ERR1
아스키 코드의 CMP AL,'F'
'A'를 빼고 JA ERR1
0AH를 더한다. SUB AL,'A'-OAH -+SKIP2: CLC ;에러가없으면 JMP CVTEND 캐리를 클리어ERR1: STC ;에러이면 캐리를 세트CVTEND: RETCVTAL ENDP;---------------------PUTASC PROC MOV DH,DL ; DL 에있는 ASCII코드 16진 값을잠깐 대피시킨다. MOV DL,' ' -+ ; DL에 있는 아스키코드 16진값을 잠깐대피시킨다. MOV AH,2
공백출력 INT 21H -+ MOV DL,DH -+ ; 대피시켰던것을 되 찾는다 MOV AH,2
아스키코드 출력 INT 21H -+ MOV DL,CR -+ ; carriage return 을 출력 MOV AH,2
복귀 개행 INT 21H
MOV DL,LF
; line feed MOV AH,2
INT 21H -+ RETPUTASC ENDPCODE ENDS ENDCVTAL은 ,GETAL로부터 호출된 서브루틴에서 아스키 코드를숫자로 변환하는것입니다.만일 숫자이외에 입력이 있을 때에는 캐리플래그가 세트되어 돌아옵니다.PUTASC 는 1문자를 띄고 지정된 아스키 코드에 상당하는 문자를 출력하고 ,줄을 바꾸는것입니다.GETAL에서는 캐리플레그가 세트되어 있는지 어떤지를 체크하여,세트되어있으면 에러로 간주 메인루틴으로 돌아옵니다.메인 루틴에서도, 역시 캐리플래그가 세트되어 있다면 에러로 간주하고 처리를 끝냅니다. 캐리 플래그에 의해서 분기하는 명령이 JC명령입니다.

asm] 어셈러브 강좌 펌 4

6.5 프로시듀어의 배치--------------------------------------------------------------------------------PROC ~ ENDP 는 사람이 보기 편하기 위한 구분에 불과하다.어셈블러는 실제로 프로시듀어를 구별하지 않는다.예제)CALL2.ASMCODE SEGMENT ASSUME CS:CODEEOF EQU 1AHSTART: CALL GETCH JC EXITP ;--+여기에서 프로시듀어를 호출하고 있다. MOV DL,AL

CALL PUTCH ;--+ JMP STARTEXITP: MOV AH,4CH INT 21HGETCH PROC MOV AH,8 INT 21H CMP AL,EOF JNE GETCHEND STC RETGETCHEND: ;긴이름의 라벨도 사용가능 그때라벨만의 행으로 해도좋다 CLC RETGETCH ENDPPUTCH PROC MOV AH,2 INT 21H RETPUTCH ENDPCODE ENDS END START ;실행시작을 알리는 문장END 문이 가지는 기능: 프로그램의 시작번지를 지정한다.이와같은것은 여러개의 코드 세그먼트를 가진 프로그램을 작성한다든지 ,프로시듀어와 메인 루틴의 순서를 바꾼 프로그램을 작성하는 경우에는 절대로 필요하다.예제)CALL2-2.ASMCODE SEGMENT ASSUME CS:CODEEOF EQU 1AHGETCH PROC MOV AH,8 INT 21H CMP AL,EOF JNE GETCHEND STC RETGETCHEND: ;긴이름의 라벨도 사용가능 그때라벨만의 행으로 해도좋다 CLC RETGETCH ENDPPUTCH PROC MOV AH,2 INT 21H RETPUTCH ENDPSTART: CALL GETCH ; 메인 루틴의 시작 <--------------------+ JC EXITP ;--+여기에서 프로시듀어를 호출하고 있다.
MOV DL,AL

CALL PUTCH ;--+
JMP START
EXITP: MOV AH,4CH
INT 21H

CODE ENDS
END START ;실행시작을 알리는 문장 >------------------+제7장 모듈별 프로그램의 작성법--------------------------------------------------------------------------------7.1 INCLUDE 의 방법--------------------------------------------------------------------------------모듈화의 이점: 프로그램을기능 별로 분활하여 알기쉽게 하는 것과 걔발효율을 향상시킬수있다아무리 같은 루틴을 사용할수있다고 하더라도 ,다른 프로그램을 만들때마다. 같은루틴을 키보드로 부터 입력하지 않으면 안된다는 것은 ,역시귀찮은 작업입니다.그래서 완성된 루틴의 부분을 미리 다른 화일 로 부터 작성해두고,메인 루틴만을 에디터로 부터 입력하여,서브루틴인 부분은 나중에 화일 단위로 결합시키는 방법을 생각해냈읍니다.이것이 어셈블러에 있는 인클루드(INCLUDE) 기능입니다.이기능을 사용할 때에는 우선 ,서브루틴 등의 부분을 독립시킨 화일로서 작성해두고 ,메인 루틴을 작성할때에 그중 필요한 부분으로 INCLUDE 의사명령을 사용하여"INCLUDE 화일 이름 " 으로 한다음 ,결합하는 화일 이름을 지정합니다.이렇게 해두면메인 루틴을 어셈블할때에 자동적으로 필요한 화일이 결합되어 어셈블됩니다.CODE SEGMENT ASSUME CS:CODE,DS:CODE;INCLUDE PUTAL.SUB ; PUTAL.SUB 화일의 내용을 인용한다.;START: MOV AX,CODE MOV DS,AX MOV AL,3FH CALL PUTAL MOV AH,4CH INT 21HCODE ENDS END STARTB 드라이브에 PUTAL.SUB 화일이 들어 있을때INCLUDE B:PUTAL.SUBINCLUDE 로 전개된 부분의 어셈블된리스트 화일은 "C " 가 붙어있다.동일 변수에 ,여러개의 데이터를 나열할때에는 다음 행에 변수이름을 가지지않는DB(define byte) 선언 등을 계속한다. NUM DB 12H,34H는 NUM DB 12H DB 34H라고 한것과 같다.레지스터의 대피:MOV BXSAVE,BX --+CALL PUTAL
BX 레지스터의 값을 대피했다가 복귀한다.MOV BX,BXSAVE --+ ..........BXSAVE DW ? ; 변수 선언7.2 PUSH,POP 명령--------------------------------------------------------------------------------PUSH,POP 명령은 ,스택 영역이라고 부르는 특별한 영역에 대하여 데이터를 기록,읽어내는 명령입니다.스택동작(stack operation)마지막에 넣은 것을 처음에 꺼내는 동작(LIFO,Last In First Out)을 스택동작메모리는 순서대로 나열되어 있으므로 ,현재어디까지 데이터가 쌓여있는지를 나타내기위하여,스택 포인터(stack pointer,ST 레지스터의 일종)에 마지막에 놓여진 데이터가 있는 메모리의 번지를 기억하도록 되어있읍니다.새로운 데이터를 쌓아올리면 SP 값은 감소 하고,데이터를 꺼내면 SP 값은 증가 번지 메모리하위번지

FFFA +-------+ FFFB +-------+ FFFC +-------+ <-- SP(스택포인터)에 의해 FFFD +-------+ 지시되는 메모리(마지막에 넣어진 데이터가 FFFE +-------+ 들어 있다.) FFFF +-------+주의) 보통의 경우와 ,데이터의 저장법과 순서가 거꾸로 되어 있으므로 주의가 요함8086의 PUSH, POP 명령에서는 반드시 2 바이트의 데이터가 한번에 읽어들여지고 꺼내어지므로, SP 의 값은 항상 2씩 증감합니다.스택영역은 보통 메모리의 최상위 번지로 설정되지만 이것은 8비트 CPU 와 같이 메모리공간이 좁은 시스템에 있어서 프로그램과 스택상의 데이터가 충돌하지 않게 하기위해서 였읍니다.8086에서는 보다 넓은 메모리 공간을 사용할수 가 있으므로 ,스택 동작을 위해서 스택 세그먼트를 독립하여 설정하고 있읍니다.SP 가 가리키는번지는 실제는 스택 세그먼트(SS)가 가리키는 베이스 번지로 부터의 오프셋 번지입니다.스택 세그먼트의 설정법에 의해 프로그램이나 데이터와 스택롸를 독립하여 배치할수도 있고,또한 8지트 CPU와 같이 프로그램과 스택을 동일한 메모리 공간에 배치할 메모리 공간에 배치할수도 있읍니다.어느경우에서도 스택 포인터의 초기치를 적당하게 설정함으로써 적당한 번지를 스택영역의 시작 번지로 할수가 있는데 ,보통은 최상위 번지로 부터시작합니다.CS -->+--------+--- 프로그램

+--------+ CS,SS ->+------------
+--------+

프로그램SS -->+--------+ +------------+ +--------+ SP스택영역 +------------+<-- SP +--------+ +------------+ 스택영역CS와 SS 를 독립시킨 경우 CS와 SS를 일치시킨 경우 ( 8비트 CPU 와 같은 사용법 )+-----------------------------------------+
PUSH +- 16비트 범용 레지트터 -+


세그먼트 레지스터


+- 16비트 메모리 -+

POP +- 16비트 범용 레지스터 -+


세그먼트 레지스터


+- 16비트 메모리 -+
+-----------------------------------------+*.POP CS 명령만은 존재하지 않는다. IP를 PUSH, POP 하는 명령은 없다. 플레그 레지스터를 PUSH, POP 하는 명령으로는 위와 별도로 PUSHF, POPF명령을 사용PUSH, POP 명령의 실제 사용 예:레지스터의 대피가 필요 하게 된것은 서브루틴 중에서 레지스터의 내용이 파괴 되기 때문입니다. 어느 레지스터의 내용이 파괴되는지는 서브루틴의 내용을 보지않고서는 알수없읍니다. 그래서 레지스터의 대피, 복귀는 메인 루틴쪽이 아니라 서브루틴 쪽에서 하는 것이 적절 합니다.+--------------+ +--------------+
메인루틴

메인루틴

........

.....

PUSH BX

CALL PUTAL

CALL PUTAL
<--+
.....

POP BX



+--------------+
+--------------++--------------+
+---------------+
서브루틴 +-----+
서브루틴
+--------------+
PUSH BX
PUSH ,POP 를 메인루틴쪽에서
.....
행한경우의 프로그램
POP BX
+---------------+ PUSH,POP를 서브루틴쪽에서 행한 경우의 프로그램완전히 같은 동작을 하지만 오른쪽이 더 좋은 프로그램입니다.메인 루틴쪽에서 어느 레지스터가 서브루틴 내에서 변경이나 파괴되는가를 생각하지않아도 되기 때문입니다.서브루틴을 완전히 블랙 박스 로서 사용할수가 있기 때문입니다.이와 같이 함으로써 서브루틴의 모듈화가 점점 효율적으로 됩니다.예제)PUSH1.ASMBL에 초기치로 주어진 어떤 8비트 값()을 1배,2배,..., F배 한수치를 출력한다.CODE SEGMENT ASSUME CS:CODE,DS:CODE;INCLUDE PUTAL2.SUBINCLUDE CRLF.SUB;ENTRY: MOV AX,CODE -+ MOV DS,AX -+DS설정; MOV BL,SEED ;초기 데이터 21H를 BL 에 지정한다. MOV CL,1NEXT: CMP CL,10H ;10H배이면 끝남. JE EXITP MOV AL,CL -+초기 데이터의 BL배를 구한다. MUL BL, -+ PUSH AX --+ MOV AL,AH -+-+---- 상위 바이트 출력 CALL PUTAL -+
POP AX --+-- AX레지스터를 보존(출력에 AL 레지스터를 사용하기 CALL PUTAL ;하위 바이트 출력 때문 ) CALL CRLF ;개행 INC CL UMP NEXTEXITP: MOV AH,4CH -+ INT 21H -+끝내고MS-DOS 로 귀환;SEED DB 21H ;초기 데이터CODE ENDS END ENTRYPUTAL2.SUBPUTAL: +--- PUSH AX -+;서브루틴 속에서 레지스터
+-- PUSH BX
AX,BX,DX 를 대피하고 있다

+- PUSH DX -+


MOV BL,10H


MUL BL


MOV DL,AH


CALL PUTHEX ; 상위자리를 출력


MOV AH,0


MOV BL,10H


DIV BL


MOV DL,AL


CALL PUTHEX ;하위자리를 출력

+- POP DX -+ AX,BX,DX 를 복귀
+-- POP BX
(PUSH와 의 역순) +--- POP AX -+ RET;PUTHEX: PUSH AX PUSH DX CMP DL,0AH JAE HEX2 ADD DL,'0' JMP HEX3HEX2: ADD DL,'A'-0AHHEX3: MOV AH,2 INT 21H POP DX POP AX RETCRLF.SUBCRLF: +-- PUSH AX
+- PUSH DX

MOV DL,0DH ;CR(복귀)을 출력

MOV AH,2 -+

INT 21H -+

MOV DL,0AH

MOV AH,2 -+ ;LF(개행)을 출력

INT 21H -+
+- POP DX +- POP AX RETPUSH,POP 명령은 16비트로 된 레지스터에 ,혹은 메모리에 대피,복귀밖에 하지 못하므로 ,서브루틴 내의 DL레지스터 밖에 사용하지 않는경우에도 DX레지스터로서 대피한다. PUSH AX ; AX의 내용을 BX에 전송 POP BX직접 전송을 허용하지 못하는 세그먼트간의 값을 전송하는데 유효합니다.예) PUSH CS POP DS가장주의 해야할점:하나의 서브루틴 중에서 PUSH 한것은 그 루틴 내에서 반드시 POP 한다.7.3 프로그램의 모듈화와 링클방법--------------------------------------------------------------------------------모듈화된 프로그램을 따로 별도로 어셈블하고 ,LINK에 의해 결합 할수도 있읍니다.+-----------------------------------------------------------------------------+
메인 프로그램 서브프로그램 메인 프로그램 서브프로그램



\/ \/

+-> MASM <-+ MASM MASM

\/ \/ \/

오브젝트 프로그램 오브젝트 프로그램 오브젝트 프로그램

\/ \/

LINK LINK

\/ \/

실행가능 프로그램 실행가능 화일



어셈블단계에서 결합하는경우 링크 단계에서 결합하는 경우
+-----------------------------------------------------------------------------+오브젝트 단계에서 링크가 가능하기 때문에 ,MS-DOS에서느 공동형식ㅇ의 오브젝트 화일을 작성하는 어셈블러나컴파일러의 출력을 합쳐서 하나의 실행가능 프로그램하는것이 가능하다.이때문에 어셈블러와 C 언어와 의 링크 등이 가능하게 됩니다.그러나 링크의 기능을 잘 사용하기 위해서는 ,많은 형식사의 약속이나 링커의 동작을 이해하지 않으면 안되아서 그 개요를 설명하는 것만해도 상당한 분량을 차지하게 됩니다.프로그램의 개발에 대해서는 메인 프로그램을 포함하는 모듈의 소스 프로그램과 서브루틴으로 이루어지는 소스 프로그램으로 작성합니다.예제)MODULE1.ASM문자열(string) We are the world 를 출력한다.CODE SEGMENT PUBLIC ASSUME CS:CODE,DS:DATA;EXTRN PUTSTR:NEAR 외부에서 참조하는 서브루틴의 선언;START: MOV AX,DATA MOV DS,AX MOV BX,OFFSET MSG CALL PUTSTR MOV AH,4CH INT 21H;CODE ENDS;DATA SEGMENT PUBLICMSG DB 'We are the world',00H;
DATA ENDS +-->끝내기 위해 삽입된 0 이다. END STARTPUTSTR.ASM문자열을 출력하는 서브루틴CODE SEGMENT PUBLIC ASSUME CS:CODE;PUBLIC PUSTR ;다른 모듈에서 참조되는 서브루틴 이름을 PUBLIC 의사명령으로; 선언한다. 즉 다른데서 PUTSTR을 참조할것이라고 선언함.PUTSTR PROC NEAR --+ PUSH AX
PUSH DX
PUSH SI
MOV SI,0
PUT_NET:
MOV DL,[BX+SI]
CMP DL,0 -+-+----->문자열중 0 이 나타나면 끝낸다. JZ PUT_EXIT -+
MOV AH,2
반드시 서브루틴 INT 21H
PROC ~ ENDP 로 INC SI
선언한다. JMP PUT_NEXT
PUT_EXIT:
POP SI
POP DX
POP AX
RET
PUTSTR ENDP ----------+;CODE ENDS 형식상 하나의 세그먼트에 있는 걸로한다. END서브루틴 PUTSTR은 ,BX에 의해 간접지정되는 번지를 선두로 한데이터 열을문자열로서 출력하고 ,0 이 나타나면 종료하는 것입니다.PUBLIC 이라는 지정은 : 다른 모듈과 링크할 때에 같은 이름의 세그먼트가 있다면 그것을 합쳐서 하나로 하라, 라는 지정입니다.EXTRN(external) : 열거된 서브루틴이 외부의 모듈의 모듈 속에 들어있다는 것을 나타내고 있읍니다.어셈블러는 더셈블 단계에서 같은 모듈 내의 서브루틴이나 라벨이 존재하지 않는 경우에는 Symbol not defined 에러를 발생하는데, EXTRN 의사명령에 의해 선언되어 있게되면 ,그서브루틴이나 라벨은 다른 모듈에 있어서 링크할때 결합할수있다고 간주되어 에러를 발생하지 않고 어셈블을 계속합니다.라벨이름이 동일세그먼트 내에 배치되는 것인 경우에는 , : 에 바로 이어서 NER을 붙이고, 라벨의 속성을 선언하지 않으면 안됩니다.만일동일 세그먼트내에 존재하지 않을 때에는 , : FAR 을 붙이지 않으면 안됩니다.서브루틴 :서브루틴에 놓이는 모듈도 하나의 세그먼트로서 형식을 갖추기위해 그 앞뒤를SEGMENT ~ ENDS 로 둘러 쌉니다.여기 에서 세그먼트선언은 메인루틴과 같지않으면 안됩니다.(동일한세그먼트 이름이어야 한다) 데이터 세그먼트를 사용하지않을 때에는ASSUME 문장으로 DS 선언을 하지 않도록 합니다.PUBLIC :의사명령 으로 PUTSTR 이라는 이름의 서브루틴(라벨 이름)이 다른 외부의 모듈에서 참조 가능하다는 것을 선언하고 있읍니다.이것은 이 루틴 중 어느 라벨 이름니 외부참조가 가능 하다는 것을 나타내는 것 입니다.여기서 사용하고 있느 PUBLC 과 세그먼트 선언중에 사용되고 있느 PUBLC과는 다른 것입니다. 그리고 서브루틴 전후를 PROC ~ ENDP 에 의해 둘러싸고, 구조를 명확하게 합니다. 이전과 마찬가지로 단순히 라벨 이름만을 서브루틴으로 할수도 있지만, 별로 추천할만 하지하지는 않습니다. 그리고 PROC 의 다음의 NEAR 은 없어도 상관이 없지만,이것도 동일한 세그먼트 내에서 참조 되는 라벨이라는 것을 나타내고 있읍니다.이상의 것을 정리하여 프로그램에 필요한 구조를 나타내고면 다음과 같이 됩니다.(세그먼트 이름을 CODE , 서브루틴 이름을 PUTSTR 로 한다.)+------------- 메인루틴 -------------------------------------+
CODE SEGMENT PUBLC

ASSUME CS:CODE.......

EXTRN PUTSTR:NEAR

START:

+---------+


본 문


+---------+

CODE ENDS

+----------------------------------+


만일 있다면 데이터 세그먼트 등


+----------------------------------+

END START
+----------------------------------------------------------------++------- 서브루틴 -------------------------+
CODE SEGMENT PUBLC

ASSUME CS:CODE.....

PUBLC PUTSTR

PUTSTR PROC NEAR

+---------+


본 문


+---------+

PUTSTR ENDP

CODE ENDS

END
+----------------------------------------------+오브젝트 화일을 링크할 때에는 화일 이름을 " + " 로 연결하여 지정합니다.반드시 메인 루틴을 포함하는 모듈의 화일 이름을 선두에 지정합니다.A>LINK MODULE1+PUTSTR,,MODULE1;이것으로 실행가능 화일이 완성됩니다.자기가 모듈을 만들어 나갈때에는 위레서 설명한 방법에 따라서 모듈으 개발하면 되는데, 아른 참고서 로 부터 인용할 경우에 반드시 위와 같은 대로 되어 있지 않은 경우가 있읍니다. 그와 같은 경우에는 세그먼트 이름을 고쳐 쓰는 방법 등으로 대처해 주십시오. 그래도 안되는겨우에는 원인을 여러가지로 생각 할수가 있지만,자세하게는 나중에 다루도록 하고 ,할수없이 서브루틴 자체를 맞도록 자기가 다시 베열 하여 고쳐 작성하는 등 시행착오를 해 보십시요.

asm] 어셈러브 강좌 펌 3

제 5장 사칙연산 명령--------------------------------------------------------------------------------가감승제의 사칙연산을 할수가 있읍니다.대부분의 8비트CPU 에 서는 곱셈 나누셈을 할수가없었는데 사칙연산을 할수가 있게 된것은 16 비트 CPU 의 큰 특징입니다.ADD 명령의 사용법:ADD AX,1234H현재의 AX의 내용에 숫자 1234H 가 더하여서 그 결과를 AX 레지스터에 다시 저장 +- 범용레지스터(8/16비트)-++- 범용 레지스터(8/16비트)-+ADD

메모리 ( " )

메모리 ( " )
+- -++- 숫자 ( " )-+양쪽 다 메로리로 조합되는것은 허용되지않음니다.*.주의 : 메모리에 수치를 더할때에는 BYTE 혹은 WORD 지정이 필요ADD [BX],12H --------> ADD BYTE PTR [BX],12H이렇게 하여 바이트 혹은 워드를 지정하지 않으면 안된다.*.주의 :AAA EQU 32H 는 AAA 가 상수이므로 [ 숫자 ] 이다.BBB DW 5678H 는 BBB가 변수이름 이므로 메모리를 나타내는 간접방식의 일종4040H+0102H 를 더하고 그결과 4142H 의 41H ,42H에 해당하는 문자를 출력한다.MAIN SEGMENT ASSUME CS:MAIN; MOV BX,4040H ADD BX,0102H MOV DL,BH ---+상위 바이트 MOV AH,2
INT 21H ---+ MOV DL,BL ---+하위 바이트 MOV AH,2
INT 21H ---+; MOV AH,4CH ---+종류 INT 21H ---+;MAIN ENDS END결과 :A>ADD1 AB A>아스키 코드 41H 에 대응하는 문자 "A" 와 42H 에 대응하는 문자 "B"가 표시직접 숫자를 숫자로 출력하는 방법은 없는것인가 ? ---MS-DOS시스템호출에 숫자를 직접 출력하는 방법이 준비되어 있지않읍니다.키입력 방법--------------------------------------------------------------------------------키보드로 부터 한문자를 입력할려면 ,MS-DOS 의 펑션호출(function)의 1 번을 사용합니다. AH 레지스터에 1 을 설정하고 펑션 호출을 수행하면, 키보드로부터 입력이 있을때 까지 기다리고 있다가 ,입력된 문자의 아스키코드를 AL register 로 돌려 보내줍니다.+------------------------------------------+
MOV AH,1

INT 21H

AL --------> 입력된 문자의 아스키코드
+------------------------------------------+MAIN SEGMENT ASSUME CS:MAIN,DS:MAIN;ONE EQU 1TOLOWER EQU 'a'-'A' ;상수나 변수의 정의 속에서 덧셈 뺄셈을 사용할수있다; MOV AX,MAIN --+DS 설정 MOV DS,AX --+; MOV AH,1 --+펑션호출로 키입력된 값이 AL에 저장된다. INT 21H
MOV KEEP,AL -+1문자입력하여 결과를 KEEP라는 변수에 저장 ADD AL,ONE ; 입력된 데이터에 1을 더하고 MOV DL,AL --+아스키 코드의 문자를 출력 MOV AH,2
INT 21H --+; MOV DL,KEEP --+2를 더한 아스키 코드의 문자를 출력 ADD DL,TWO
MOV AH,2
INT 21H --+; MOV DL,KEEP --+ 20H를 더하여 소문자로 변환하여 출력 ADD DL,TOLOWER
MOV AH,2
INT 21H -+; MOV AH,4CH --+ INT 21H --+ 종료하고 OS로 돌아간다;TWO DB 2KEEP DB ? ;단순히 데이터를 저장하기위하여MAIN ENDS END'a'-'A'는 a 와 A 의 아스키 코드의 차이를 나타낸다.'a' 에 대응 하는 아스키 코드 61H 로 부터 'A' 에 대응하는 41H 를 뺀61H - 41H = 20H 를 의미 합니다. 따라서 TOLOWER 에는 숫자 20H 가 저장디버거의 사용 예와 역워드 형식--------------------------------------------------------------------------------예제1000H + 1234H를 계산하여 ANS1에 저장한다.AMIN SEGMENT ASSUME CS:MAIN,DS:MAIN; MOV AX,CS MOV DS,AX; MOV AX,1000H MOV BX,1234H ADD AX,BX MOV ANS1,AX; MOV AH,4CH INT 21H;ANS1 DW 0000 ------> MOV [0013],AX 로 역어셈블된다,즉 변수ANS1은; 0013H 번지 할당되어 있기 때문에MAIN ENDS ENDDEBUG 는 EXE 및 COM 형 실행 화일 을 로드 하였을 때에는 실행할수있는 상태로레지스터 종류를 세트하여 대기하고 있읍니다그외의 화일을 로드 하였을 때는 단순히 로드하였을때의 화일의 선두 번지를 CS:IP에 넣고 대기 하고 있읍니다.역어셈블된 ANS1 변수의 번지 0013 을 보면 3422 가 들어 있다역어셈블 결과의 XOR AL,22 라는 것은 단순히 이 데이터를 명령으로보고 역어셈블해버린것이므로 아무의미가 없다원래의 연산결과는 1000H + 1234H = 2234H 라고 될터인데 0013H 번지와 0014H 번지에는 3422 로서 저장되어 있다는 것입니다.즉,상위와 하위가 서로 바꿘 형태로 결과가 저장되어 있음니다.80 계열CPU의 특징적인 현상으 로 ,16비트 레지스터 상의 데이터(워드데이터)를 메모리에 전송할때에는 상위 하위 바이트가 바꿘다라는 규칙이 있기 때문입니다.이와 같은 전송방식을 역워드 형식 이라고 합니다.메모리 상에 데이터를 저장할 때에는 상하 바이트가 바뀌므로 다시 이것을 레지스터 상 에 전송할때에는 ,또한 상하 바이트가 바뀌어서 전송되기 때문에 바른 형태로 데이터를 전송할수가 있읍니다.따라서 어셈블러를 사용하여 프로그램을 작성할때에는 역워드로 되는 것은 별로 의식할필요가 없읍니다.자리올림(carry)과 ADC 명령--------------------------------------------------------------------------------16비트 레지스터에 저장되지 않는 것을 미리 알고 있는 경우에는2개의 16비트 레지스터를 사용하여 32비트 숫자를 표시 ,하위 16비트 를 덧셈할때에발생한 자리올림( carry ) 을 어딘가에 기억해 놓고 ,상위 16비트를 덧셈할때 더해주는 방법을 취합니다자리올림을 기억하는 플래그 레지스터 중의 캐리 플래그(carry flag)비트덧셈을 할때에 캐리 플레그를 동시에 더하는 ADC 명령(ADdition with Carry)MAIN SEGMENT ASSDUME CS:MAIN,DS:MAIN; MOV AX,MAIN MOV DS,AX; MOV AX,1000H MOV BX,8000H MOV CX,2000H MOV CX,8123H ADD BX,DX ;두개의 16비트의 합을 구한다 ADC AX,CX ;위에서 생긴 캐리까지 고려하여 상위16비트합을구한다. MOV ANS1,AX MOV ANS2,BX; MOV AH,4CH INT 21H;ANS1 DW 0ANS2 DW 0;MAIN ENDS END데이터를 교환하는 XCHG 명령--------------------------------------------------------------------------------XCHG (exchange) 명령은 2 개의 데이터를 교환하는 명령직접숫자를 교환할수는 없읍니다.메모리끼리의 교환도 불가능합니다.첫번째 두번째 오퍼랜드는 일치되어야 합니다.XCHG +- 범용 레지스터 (8/16비트) -+ +- 범용 레지스터 (8/16비트) -+ +- 메모리 (8/16비트) -+, +- 메모리 (8/16비트) -+MAIN SEGMENT ASSUME CS:MAIN,DS:DATA; MOV AX,DATA MOV CS,AX; MOV AX,1000H MOV BX,8000H MOV CX,2000H MOV CX,8123H ADD BX,DX ;두개의 16비트의 합을 구한다 ADC AX,CX ;위에서 생긴 캐리까지 고려하여 상위16비트합을구한다. XCHG AL,AH XCHG BL,BH MOV ANS1,AX MOV ANS2,BX; MOV AH,4CH INT 21H;MAIN ENDS;DATA SEGMENTANS1 DW 0ANS2 DW 0DATA ENDS END이번에 주의 하지 않으면 안되는 것은 ,지금까지와 달라 서 데이터 세그먼트가 별도로설정되어 있다는 사실입니다.이 경우에는 어셈블할 때에는 데이터 세그먼트의 위치는 결정되지 않고 ,링커에 의해상대적인 배치가 정해진 다음 실행할때에 절대 번지가 결정됩니다.따라서 어셈블할 때에 MOV AX,DATA 에 대응 하는 부분은 B8 --- R 로되어 있으므로메모리 사에 로드 하였을 때에는 MOV AX,2245 와 같이 값이 결정되어 있읍니다.자, 여기에서 데이터를 볼려면 세그먼트 베이스와 오프셋 번지를 같이 지정하여 내용을 표시 하지 않으면 안됩니다.역어셈블한 결과 데이터 세그먼트에 세트되는 값은 ,2245H 라는 것을 알수있읍니다._D2245:0,F2245:0000 00 00 00 00 F4 75 10 8B - 7E EE 39 3E 42 1F 76 07.....tu..~n9>B.V.여기서 D 는 데이터를 보이라는 명령 (DUMP ) 0,F 오프셋 번지 지정 2245 는 데이터 세그먼트의 베이스 번지가 2245 이다.SUB 명령의 사용법(뺄셈 명령)--------------------------------------------------------------------------------SUB +- 범용레지스터(8/16비트) --+ +- 범용레지스터 (8/16비트) --+ +- 메모리 (8/16비트) --+
메모리 (8/16비트)
, +- 숫자 (8/16비트) --+메모리 자체끼리는 뺄셈을 할수없다:SUB (subtract) 명령은 첫번째 오퍼랜드로 부터 2번째 오퍼랜드 의 내용을 뺀다음결과를 첫번째 오퍼랜드에 저장합니다.예제) SUB1.ASM변수 AAA 의 200 에서 100 을 빼는 프로그램MAIN SEGMENT ASSUNE CS:MAIN,DS:MAIN; MOV AX,MAIN MOV DS,AX MOV AL,100 ; 16진수로 64H SUB AAA,AL; MOV AH,4CH INT 21H;AAA DB 200 ; 16진수로 C8H;MAIN ENDS END어셈블러에서는 끝에 숫자의 표기법을 나타내는 (H) 나 (B) 가 붙어 있지않으면내정적으로 10진수로써 취급합니다.SBB 명령(subtract with borrow)--------------------------------------------------------------------------------캐리와 함께 뺄셈을 하는 SBB 명령:자리 빌림이 발생하면 캐리 플레그가 세트된다.사용법:1) SUB명령에 의해 하위 16비트(혹은 8비트)를 뺄셈2) SBB명령에 의해 상위 16비트(혹은 8비트)를 뺄셈만일 처음부터 16비트 연산에 SBB명령이나 ADC 명령을 사용하면캐리 플래그가 이전부터 가지고 있었던 연산과 직접 관계없는 값까지 뺀다든지더해버리는 경우가 있기 때문입니다.예제) SUB2.ASM12340000H - 1000H 를 계산하는 프로그램MAIN SEGMENT ASSUME CS:MAIN,DS:MAIN; MOV AX,MAIN MOV DS,AX; MOV WORK1,1234H MOV WORK2,0000H MOV WORK2,1000H SBB WORK1,0000H; MOV AH,4CH INT 21H;WORK1 DW 0WORK2 DW 0;MAIN ENDS END여기 프로그램에서 하려고 하는 계산을 식으로 나타내면 12340000H- 1000H------------- 1233F000H 라는 것이 됩니다.WORK1 이 상위 16비트 ,WORK2 가 하위 16비트로 메모리에 직접 숫자를 대입하고 ,뺄셈을 하고 있읍니다. 여기에서 연산하기 전에 WORD PTR 이 붙어 있지 않았는데 ,이것은 변수이름이 DW 에 의해 명확하게 WORD 형의 속성을 갖고 있기 때문입니다.이와같이 변수에 숫자를 대입할 경우에는 형(type) 지정이 필요없읍니다.다만 디스어셈블할 때에는 WORD PTR 이 붙습니다.예) SUB3.ASM변수를 경제적으로 PTR 지정에 의해 지정된 형(type)으로 사용한 예MAIN SEGMENT ASSUME CS:MAIN,DS:MAIN; MOV AX,CS MOV DS,AX; MOV AH,11H MOV BH,22H MOV CL,33H MOV SI,4444H MOV BP,5555H ADD AH,66H MOV BYTE PTR ANS1,AH ADD CL,0FFH ADC BH,0H MOV BYTE PTR ANS2,BH MOV BYTE PTR ANS2+1,CL SUB BP,SI MOV WORD PTR ANS3,BP; MOV AH,4CH INT 21H;ANS1 DW 0ANS2 DW 0ANS3 DB 0ANS4 DW 9999H;MAIN ENDS END선언된 형 이외에서의 변수의 사용법--------------------------------------------------------------------------------앞에서 ANS1,ANS2 등과 같은 것은 번지를 나타내는 이름이들 변수이름은 선언된 형(바이트 인지 워드 인지)을 속성으로 서 지니고 있으므로 그대로 사용하였을 때에는 그 선언된 형 이외의 형태로 사용하고 싶을때에는 '형 + PTR ' 을 붙임으로써 강제적으로 다른 형으로 사용할수가 있읍니다.MOV BYTE PTR ANS2+1,CL 라는 부분은 :변수이름에 대한 덧셈 뺄셈은 ,번지의 값을 덧셈,뺄셈한다.(ANS2 가 나타내는 번지 +1)그러나 실제로느 이와 같은 사용법은 별로 추천하지는 않습니다.특수한경우를 제외하고는 변수는 선언된 형으로 취급하도록 하는 것이 현명합니다.음수와 보수 표현--------------------------------------------------------------------------------보수(complement)의 개념:10진수로 100을 기준으로 한경우의 5의 보수는 100-5=95,따라서 5의 보수는 95이다.16진수의 1바이트 = 8비트숫자로 0 ~ 255 (= 28 - 1 = 0FFH)까지의 숫자를 취합니다.28(=100H) 를 기준으로 한 보수를 생각 합니다.2의 보수는 100H - 2H = 0FFH28을 기준으로 한 3의 보수 100H - 3H = OFDH여기에서 -1을 나타내는 데에 1의 보스를 사용하여 0FFH -3을 나타내는 데에 3의 보스를 사용하여 0FDH 등으로 표현예)1+(-1)=01H+0FFH=100H ---> 01+(-3)=01H+0FDH=0FEH ---> -2여기에서 주의사항 : 보수 표현 을 사용한 경웅에 어느수가 음수를 나타낸것인가를 결정하지 않으면 안된다는 것입니다.아무표시도 안하면 0FDH 가 정수의 253 인지,음수의 -3인지 알수가 없다.그래서 보수표현을 사용한 경우의 약속으로서 그숫자를 2진수로 나타냈을때,최상위 비트(MSB)가 0 인 것을 양수,최상위 비트가 1 인것을 음수로 간주하도록 정하고 있읍니다.이렇게 하면, 8비트 숫자에서는 0 ~ 7FH 까지가 양수, 80H~ 0FFH 까지가 음수(-80H ~-1H 에 대응) 이것에 의해 -80H~ +7FH 까지의 숫자를 나타낼수가 있읍니다.16비트 숫자를 취급하는 경우에도 마찬가지로 216=10000H를 기준으로 0~7FFFH 까지가 양수 8000H~ 0FFFFH까지가 음수MSB : most significant bit 의 약자이고 최상위 비트를 표시함LSB : least significant bit 의 약자이며 최하위 비트를 말한다. MSB LSB8비트의 경우
+-+-+-+-+-+-+-+-+ +-> +-+-+-+-+-+-+-+-+ 7 6 5 4 3 2 1 0 MSB LSB16비트의경우
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1514131211109 8 7 6 5 4 3 2 1*.주의 )보수표현을 사용하여 -80H ~7FH 까지의 수를 취급할 것인가,보수표현을 사용하지않고0~0FFH까지의 숫자를 취급할것인가는 프로그래밍을 하는 사람이 정하는 것으로서 같은숫자가 양수르 의미하는 것인가 ,음수를 의미하는 것인가는 경우에 따라 다르다 라는 것입니다.취급하는 숫자가 양수뿐이고 뺄셈을 하지 않는 경우에는 보수표현을 사용할필요가 있읍니다어느것을 사용할것인가는 프로그램의 목적에 따라 결정하지 않으면 안됩니다.어셈블러에서는 양수 음수가 어떤식으로 해석되는가를 봅시다.원래 숫자가 1H 및 0FFH인 경우 그숫자가 그대로 레지스터로 전송되는 숫자가 됩니다.원래의 숫자가 -1H 및 -0FFH 는 , 단순히 보수로 변환되어서 전송하는 숫자로 됨.8비트 레지스터로 -0FFH를 전송하는 경우: 1H 로바른 변환이 아니다어셈블러에서는 보수표현이 가능한 상하의 범위의 검사는 하지않으므로 주의가 필요함-0FFH를 바르게 취급하려고 한다면 8비트 레지스터로는 불가능하고 ,16비트 레지스터를 사용할필요가 있읍니다 .16비트 숫자는 메모리상으로는 역워드 형식으로 기억되어 있으므로MOV AX,1234HB8 1234 가 아니라 B8 34 12 로 나열되어 있음니다.부호 확장 명령--------------------------------------------------------------------------------40H와 50H 를 더하면 결과는 90H 가 되는데 ,이것은 보수 표현에서는-70H 라는 음수에 해당 되므로 바른 결과 가 아닙니다.(10010000 의 2의 보수는 우선 1의 보수로서는 01101111 이되고01101111+1=01110000=70H 가 된다.최상위 비트가 1이므로 음수 -70H 가 된다.)ADD DL,AL ----->가능ADD DX,AL ----->레지스터 불일치 따라서 불일치레지스터의 전송이나 덧셈 뺄셈에서는 2개의 ,레지스터의 크기가 같지 않으면 안됨양수의 덧셈:모든 수를 양의 정수로서 취급하는 경우 - 8비트 레짓스터의 값을 16비트로 확장한다음 더하면 됩니다.MOV AH,1 --+ 한 문자 입력 루틴 결과는 AL 레지스터에 놓여진다.INT 21H --+MOV AH,0 ----> AL 레지스터의 상위 8비트를 클리어 한다.ADD DX,AX양수만을 취급할때에는 상위 바이트에 00을 대입한다.AL =41H +--------------+
AX
한문자 입력후의 각레지스터의 상태 +-------+------+ ("A "=41H 를 입력한 경우 )
AH
AL
+-------+------+
미정
41
+-------+------+===== AH 레지스터에 0 을 대입 8비트 데이터를 16비트 데이터로 확장 =====AX=0041H +--------------+
AX
한문자 입력후의 각레지스터의 상태 +-------+------+ ("A "=41H 를 입력한 경우 )
AH
AL
+-------+------+
00
41
+-------+------+예제) SGN2.ASM4개의 숫자 50H,60H,80H,F0H를 합하여 ANS에 저장한다.MAIN SEGMENT ASSUME CS:MAIN,DS:MAIN; MOV AX,CS MOV DS,AX; MOV AX,0 MOV DX,0 MOV DL,VAR1 ADD AX,DX MOV DL,VAR2 ADD AX,DX MOV DL,VAR3 ADD AX,DX MOV DL,VAR4 ADD AX,DX MOV ANS,AX; MOV AH,4CH INT 21H; VAR1 DB 50H VAR2 DB 60H VAR3 DB 80H VAR4 DB F0H ANS DW ?;MAIN ENDS END디버거 상에서 실험하여 확인해 볼것(HWP에서 F3지울영역설정,ctrl-E 지우기 실행,예제를 아스키로 세이브 MASM 실행)이방법은 256이란 수치까지는 안심하고 덧셈을 할수가 있읍니다.보수표현에 의해 많은 데이터를 더하는 법--------------------------------------------------------------------------------음수는 상위 바이트에 00을 대입하기만 하는 것으로 는 안됨,(음)95H ----> 0095H(양)(음)F7H ----> 00F7H(양)따라서 음수를 8비트에서 16비트로 변환할때에는(음)95H ----> FF95H(음)(음)F7H ----> FFF7H(음)(음)80H ----> FF80H(음)양수이면 상위 바이트에 00을 대입 ,음수이면 상위 바이트에 FF를 대입한다.이와 같은 작업을 일일이 프로그램을 작성하여 하려고 한다면 대단히 곤란할것 입니다.그래서 위에서 기술한 규칙에 따라 8비트 숫자를 16비트로 변환해주는 명령으로서CBW (convert byte to word) 명령을 만들어 놓았읍니다.이것을 부호확장명령 이라고 합니다.보수표현을 사용하여 양수 음수를 사용하는 경우에는최상의 비트가 0 인 것을 양수, 1 인것을 음수라고 한다.8비트 수치를 16비트 수치로 확장할때에:최상의 비트가 0 이면 상위 8비트 모두에 0을 대입,최상의 비트가 1 이면 상위 8비트 모두에 1을 대입 양수의 확장 음수의 확장8비트 0XXXXXXXX 1XXXXXXX +-------+ +-------+ V V V V16비트 000000000XXXXXXX 111111111XXXXXXXCBW ....AL레지스터의숫자를 부호확장하여 AX 레지스터에 저장한다.CWD ....AX레지스터의 숫자를 부호확장하여 ,상위16비트를 DX레지스터에 , 하위 16비트를 AX 레지스터에 저장한다.CWD (convert word to double word ) 32비트 레지스터로 간주하는 명령부호 확장명령의 사용법:예제) SGN3.ASM부호가 붙은 4개의 숫자를 합하여 ANS 에 저장하는 프로그램MAIN SEGMENT ASSUME CS:MAIN,DS:MAIN; MOV AX,CS -+DS 초기설정 MOV DS,AX -+; MOV AX,0 -+AX,DX 를 0으로 클리어 MOV DX,AX -+ MOV BX,OFFSET VAR ;변수이름 VAR이 가리키는 오프셋 번지 를 BX에 저장 MOV AL,[BX] ;BX에 들어있는 번지값의 내용을 AL 에 넣는다 CBW ;부호 확장 ADD DX,AX ^ MOV AL,[BX]+1 -+ 번지의 표기법에는 여러종류가있다.
CBW

ADD DX,AX

MOV AL,[BX+2] -+ C 언어의 포인트 개념과 같다.---+ CBW
ADD DX,AX
MOV AL,3[BX] -+ CBW ADD DX,AX MOV ANS,DX; MOV AH,4CH INT 21H;VAR DB 50H,60H,80H,0F0H ;데이터를 연속하여 할당시킨다.ANS DW ?;MAIN ENDS END주의 ) CBW 명령은 AL 레지스터로부터 AX 레지스터로 밖에 변환할수없다.VAR변수는 :(독립된 변수이름이 주어져 있지 않읍니다.)VAR DB 50H DB 60H DB 80H DB 0F0H와 같이 지정하여도 똑같읍니다.여기서 변수의 내용을 꺼내기 위해서 변수이름 VAR이 나타내는 번지로부터 상대의 위치를 지정할필요가 있읍니다.MOV BX,OFFSET VAR(오프셋 의사명령에 의해 변수이름이 가지는 속성의 하나인 오프셋 번지의 값을 꺼낼수있다 .)번지의 표기법중에서[BX]+2[BX+2]2[BX] 는 완전히 같은 방법을 다른 방법으로 썼을 뿐이다.디버거에서는 역어셈블할 때의 표기는 [BX+2]의 형식으로 되어있다.단, 변수이름을 사용해도 마찬가지 입니다.[BX]+1 은 VAR+1 등으로 치환할수가 있읍니다.여기에서 VAR + 1 이라는 것은 변수의 내용에 1 을 더하는 것이 아니라변수이름이 나타내는 번지에 1 을 더한다.[BX+2] 는 VAR+2 로3[BX] 는 3+VAR 로 라는 식으로 바꿀수가 있읍니다.*.보수로 표시된 80H 가 왜 -80H 가 되는가.?80H =1000 0000 이어서 MSB=1 이므로 음수이다. 우선 1 의 보수를 취하면 0111 1111.여기에 +1 하면 1000 0000 즉 80H 가 되므로 -80H 값이다.여기에서는 결과를 숫자로서 출력하는 루틴을 덧붙이지 않았다.매번 사용하는 루틴은 한번 작성해두면 나중에 다른 프로그램을 만들때에 인용할수있도록 하기위해서 루틴을 다른 화일 로 작성해두고 INCLUDE 문으로 포함시키는 기능이나,분할 컴파일 하여 오브젝트 화일로 작성해두고 LINK 에 의해 링크하는 기능도 있읍니다.. 당분간은 결과를 디버거 를 사용해서 하도록합시다.

asm] 어셈러브 강좌 펌 2

제 4장 데이터 전송 명령--------------------------------------------------------------------------------MOV 명령과 문자 출력데이터의 입출력과 전송명령에 대해서 해설 합니다.*.레지스터에 수치를 대입한다.*.레지스터와 레지스터 사이에서 데이터를 전송한다.*.레지스터와 메모리 사이에서 데이터를 전송한다.화면에 " AB " 를 표시 하는 프로그램MAIN SEGMENT ; 세그먼트를 알리는 의사명령 ASSUME CS:MAIN ;; MOV DL,41H ; 아스키코드 41H ' A ' 자 이다. MOV AH,2 INT 21H MOV DL,'B' MOV BL,2 MOV AH,BL INT 21H; ; 단순히 줄을 띄우기 위해 삽입된 설명문 MOV AH,4CH ; 프로그램의 끝냄 INT 21H;MAIN ENDS END자기가 작성한 소스프로그램을 그대로 보고 싶으면 리스트 화일인 .LST 를 살펴보는 것이 좋다.의사명령은 직접 기계어로 번역되지 않지만 , 어셈블 작업의 흐름을정할때에 중요한 역할을 해 줍니다.여기서 MAIN 은 어떤 이름이든지 상관없다.ASSUME CS:MAIN이라는 의사 명령은 어셈블러가 어셈블을 할때 코드세그먼트(CS:)를 참조 하라는 명령이 있으면 MAIN 이라는 이름의 세그먼트를 참조하라는 선언 을 하는 문장입니다.ASSUME 문장은 4개의 세그먼트(CS,DS,SS,ES)와 세그먼트 이름을 대응시키는 선언문입니다.명령은 반드시 CS:(코드세그먼트 )에END 문으로 어셈블러는 끝난다. END 문으로 시작번지를 지정할수가있다.어셈블러 프로그램의 기본형AMIN SEGMENT ASSUME CS:MAIN .......... 본 문 ..........MAIN ENDS END설명문 (comment, 주석문)을 쓰는법;은 설명문 행 입니다. ; 이 다음 부터 쓰여진 문자는 설명문입니다.8086 의 레지스터(register)--------------------------------------------------------------------------------범용 레지스터 AX,BX,CX,DX 는 8 비트로 나누어 사용할수 있다.범용 레지스터 SI,DI,BP,SP 는 16 비트로서 밖에 사용 할수 없다.어셈블러에서는 특별히 표시하지 않는한 수치는 10진수로서 취급됩니다.16진수를 사용할때는 숫자의 뒤에 H(Hexa decimal) 를 붙여서 표시합니다.수치가 알파벳으로 시작할때는 " 0 "을 붙여 변수이름과 혼동을 피한다.MOV DL, 41H ; DL <----- 41H 41H를 DL 에 대입하라. +---


----------+
+----+
행선지(DESTINATION), 출원지(SOURCE)시스템 호출과 입출력은 INT 21H <---- 인터럽트 (interrupt-끼어들기) 명령은강제로 CPU가 하던 일을 중지시키고 끼어들기MOV DL,'1' ; 문자를 인용부호로 에워싼 것을 오른쪽에 쓴경우에는 그문자에 대응하는 아스키코드가 쓰여진 것으로 간주됩니다. 1 은 아스키코드값 31H 로 대치됩니다.프로그램을 끝마치는 방법MOV AH,4CH ; MS-DOS 의 SYSTEM CALL 인 4CH 번째의 루틴INT 21H ; 프로그램을 마치고 OS 레벨로 돌아간다.데이터를 두는 방법(1)--------------------------------------------------------------------------------프로그램중에 데이터를 두고 , 그 데이터를 레지스터에 전송하는 방법을 설명변수이름 선언법 :XXX DB 'X' ; DB 는 define byteYYY DW 3456H ; DW 는 define word

---------> 변수에 들어 가는 초기치
+---------------->변수의 형+----------------------->변수이름DB ..... 바이트의 정의DW ..... 워드(2바이트)정의DD ..... 더블 워드(4바이트)정의DQ ..... 쿼트 워드(8바이트)정의DT ..... 10 바이트 정의*.사용법 +----------+--------+-----------+
변수이름
DB
식
+----------+--------+-----------+세그먼트를 정의 하는 ASSUME 의사 명령MAIN SEGMENT ASSUME CS:MAIN, DS:MAINMAIN : 세그먼트 개시를 선언CS:MAIN 코드세그먼트가 MAIN 이라는 이름의 세그먼트에 연결되어있다는것DS:MAIN 데이타세그먼트가 MAIN 이라는 이름의 세그먼트에 연결되어 있다는것8086에서는 데이타는 데이타세그먼트 내에 있는 것으로서 해석되므로 ,데이터세그먼트가 어디있는가 를 지정해야한다.명령도 데이타도 둘다 MAIN 이라는 이름의 세그먼트 내에 있으므로ASSUME CS:MAIN, DS:MAIN그러나 이것은 어셈블러에 대한 지시이다데이타를 처리하는 명령으로는 번역되지않는다세그먼트를 초기설정(initialize) 하기위해서는MOV AX,CSMOV DS,AX이와같이하여 ,AX 레지스터를 경유하여 DS 에 CS 의값을 전송하여2 개의 세그먼트를 일치시키지않으면 안됩니다.이것은 어셈블러의 정해진 문구입니다.여기서MOV DS,CS라고 할수는 없읍니다.세그먼트 레지스터(CS,DS,SS,ES)는 범용 레지스터들로 밖에는데이터를 전송하는 것이 허용되어 있지않기 때문입니다.세그먼트 레지스터에 직접 숫자나 변수를 대입할수는 없읍니다.어셈블 리스트에서8A 16 0020 RR .... 이라는 문구는 상대번지(relative address) 지정방식임을 나타내고 있읍니다.데이터를 두는 방법(2)--------------------------------------------------------------------------------여러개의 세그먼트에 두는 법MAIN SEGMENT ---+ ......
MAIN ENDS ---+DATA SEGMENT ---+ .....
DATA ENDS ---+ 이와 같은 두개의 세그먼트가 존재하게 설계한다.ASSUME CS:MAIN,DS:DATA데이터를 참조하는 명령이 있는 경우에는 데이터는 DATA 라는 이름의 세그먼트에 있다고 간주하고 명령을 작성하라는 지시입니다.MOV AX,DATAMOV DS,AX데이터의 세그먼트의 값을 초기 설정하는 부분입니다.프로그램을 시작할때 데이터 세그먼트의 지정법만 잘 익혀두면 본분 중에서는 데이터가 어느 세그먼트 내에 있는가 신경쓰지 않고 ,프로그램을 작성할수있읍니다.번지의 간접 지정법(1)--------------------------------------------------------------------------------바이트형 데이터는 연속하여 정의할수있다.DB 를 사용하여 데이터를 정의 하는 경우에 ' ABC ' 와 같이 연속하여 몇 문자라도데이터를 정의 할수가 있읍니다.XXX DB 'ABC' ------+ 모두같다.XXX DB 'A','B','C'
XXX DB 41H,42H,43H ---+
+---->DW,DD,DQ,DT 와 같은 다른 변수형의 데이터도 나열할수는 있습니다.그러나 수치로써는 가능하지만 문자열로써 주어지는 경우는 한번에 2문자 씩의 문자열밖에 줄수가 없다.AAA DD 'AB','CD','EF'는 허용이 되지만AAA DD 'ABCD', 'EFGH' 는 허용이 안된다.DB 의 경우에만이 특별하고 3 문자 이상의 문자열의 나열을'A','B','C' 로 하는 대신에 'ABC' 로 할수있다.자,그럼 어떻게 XXX 라는 변수이름의 장소에 서 나열되어있는 데이터를 꺼내어 쓸수가있는가MOV AL,XXX라고 하면 XXX 의 장소에 나열된 문자열의 제일 처음 의 것인 'A'=41H 가 AL 레지스터에 전송됩니다.(XXX라고 하는 이름의 장소에 있는 데이터를 AL레지스터에 전송하라)변수가 자리잡고 있는 번지를 꺼내는 오프셋(OFFSET 명령):MOV BX,offset XXX
변수이름이 붙여진 번지 자체의 값을 BX 레지스터에 전송하 +-----> 는 명령입니다.OFFSET : 변수이름이 붙여진 데이터가 있는 번지를 꺼내는 연산자.오프셋번지 : 세그먼트를 기준으로 한 번지MOV BL,XXX ; BL 과 XXX 는 8 비트 이므로 가능MOV BX,XXX ; BX 는 16비트 레지스터, XXX는 8비트 레지스터이므로 에러[ ] 를 사용한 간접 번지 지정방식:어떤번지의 내용을 꺼낼때에는 [번지 ] 와 같이 [ ] 를 붙인다.MOV DL,[1FH] ; 1FH 번지에 있는 데이터를 DL 레지스터로 전송하라BX 레지스터내에 변수 XXX 의 처음 데이터가 DL 레지스터로 전송됩니다.그 다음은 이것을 표시 합니다.2 번째 데이터는 선두 번지 +1 번지에 저장되어 있으므로, 여기서는 BX + 1 번지의내용을 꺼내면 되는 것입니다.같은 방법으로 BX+2,BX+3 .......MOV DL,[BX+1][ ] 내의 값이 나타내는 번지에저장되어 있는 내용을 꺼내는 것을 지시하고 있읍니다.이와 같은 지정법을 간접지정방식(indirect addressing )이라고 부릅니다.MOV AX,[1234H]와 같은 지정법도 간접번지 지정방식의 일종으로서의직접번지지정방식(direct addressing mode) 이라고 부릅니다MAIN SEGMAIN ; *.데이터를 세그먼트 내에두는 경우 ASSUME CS:CODE,DS:DATA MOV AX,DATA MOV DS,AX +-----------+
본 문
+-----------+MAIN ENDSDATA SEGMENTXXX DB 'ABC'DATA ENDS END번지의 간접 지정법(2)--------------------------------------------------------------------------------간접지정에 사용할수 있는 레지스터는 4개뿐이다BX,BP,SI,DI왜그런가 하는 것은 8086 설계자가 정해놓은 일이다.[BX+DI][BX+SI+1]와 같은 이들끼리의 조합지정이 가능 합니다예) [BX+SI+4]BX=1000HSI=1234H 인 경우1000H + 1234H + 4H = 2238H 이 된다.간접지정 조합법의 규칙:+----+ +-------+ +--------------+
BX

SI

16비트 숫자

BP
+
DI
+
8비트 숫자

없다

없다

없다
+----+ +-------+ +--------------+ [BP] 는 단독으로 사용할수가 없음니다.단순히 기계적 제약에서 오는 것입니다 사용하고 싶다면 [BP+0] 으로 합니다.MOV DL,[BX+SI]; BX에는 변수의 시작번지 , SI에는 3을 대입,따라서 DL 에는 변수의 선두로 부터 4 번째 바이트의 데이터가 DL 레지스터에 전송한다 . *.SI= 0 부터 선두를 가리킨다.예제) MOV5.ASM메모리에서 저장된 문자열" ABCDEFG" 중 네번째, 다섯번째 문자 DE 를 출력MAIN SEGMENT ASSDUME CS:MAIN,DS:DATA; MOV AX,DATA MOV DS,AX MOV BX,OFFSET AAA MOV SI,3 MOV DL,[BX+SI] MOV AH,2 INT 21H MOV DL,[BX+SI+1] MOV AH,2 INT 21H;MAIN ENDS;DATA SEGMENTAAA DB 'ABCDEFG';DATA ENDS END*. 간접지정에 사용 하는 레지스터에 BP 레지스터가 포함되는 경우에는 , 스텍세그먼트(SS:)에 데이터가 있는 거으로서 해석된다.( 보통은 BP 레지스터를 사용한 간접 지정법은 안하는것이 무난할 것입니다. )간접 번지 지정방식의 사용법--------------------------------------------------------------------------------CODE SEGMENT ASSUME CS:CODE,DS:DATA; MOV AX,DATA ; DS를 설정 MOV DS,AX; MOV BX,OFFSET AAA ; AAA의 번지값을 BX 에 대입 MOV AX,'AB' ; 문자 하나는 8비트 MOV [BX],AX ; BX 가 가리키는 AAA 변수에 'AB'를 넣는다 MOV CX,AAA MOV DL,CH ; DL 에 A 를 넣는다 MOV AH,2 ----+ INT 21H ----+ 문자 A를 보인다. MOV DL,CL ; DL 에 B 를 넣는다. MOV AH,2 ----+ 문자 B를 보인다. INT 21H ----+ MOV AH,4CH INT 21H ; 종료하고 OS 로돌아간다.;CODE ENDS;DATA SEGMENTAAA DW ; AAA 라는 변수를 위해서 워드 영역을 확보하라DATA ENDS ENDAAA DW ? 는 '? ' 는 숫자는 아무것이라도 좋다라는 의미입니다.이밖의 사용법으로는MOV [BX+SI+5],1234HMOV AAA,'AB'라는 사용법이 가능 합니다.MOV [BX],[SI+3]그러나 이와 같은 ,오퍼랜드 양쪽 다 간접지정으로 할수는 없읍니다.MOV BX,[0008] -----> 8 번지의 내용을 꺼내온다 라는 간접 지정방식레지스터를 사용하지않고 수치만으로 번지를 지정하는 이러한 방법을 직접번지 지정(direct addressing)이라고 말합니다.또한, MASM 에서는 이와 같은 직접 번지 지정방식을 어셈블러 속에 쓸수가 없읍니다.그것은 메모리 번지는 링커에 의해 동적(dynamic)으로 활당되기때문에 ,고정된 번지 지정방식을 사용 할수없다고 가정되기 때문이라고 생각됩니다.EQU 의사 명령--------------------------------------------------------------------------------상수를 정의 하는 EQU 의사 명령MAIN SEGMENT ASSUME CS:MAINCHAR1 EQU 'A' ;'A' = 41H 가 정의 됩니다 --+CHAR2 = 42H ; = 는 재정의가 가능
DISP EQU 2 ; EQU는 재정의가 불가능, --+상수는 어셈블할때 치환; MOV DL,CHAR1 MOV AH,DISP INT 21H MOV DL,CHAR2 MOV AH,DISP INT 21H MOV AH,4CH INT 21H;MAIN ENDS ENDEQU 의사명령에 의한 상수의 정의와 DB 등에 의한 변수의 정의와의 차이는 :EQU 에 의해서 선언된 상수 - 어셈블할때 직접숫자로 치환DB 등에 의해서 선언된 변수 - 데이터가 저장되어 있는 번지로서 치환예)MOV CHAR1,DL -----> 불가능'=' 에 의해서 정의된 숫자를 다시 정의 할때는 ,다시 '=' 를 사용해서 정의 한다.어셈블러는 시작순서대로 어셈블을 해나가면서 가장 최근 에 정의된 숫자를 그 상수의 숫자로써 사용합니다.따라서 다음과 같이 됩니다.CHAR1 = 41H MOV DL,CHAR1CHAR1 = 56H MOV DL,CHAR1결과 := 00410000 B2 41= 00560002 B2 56데이터의 형과 PTR 연산자--------------------------------------------------------------------------------데이터의 형(type):바이트,워드(2바이트),더블워드(4바이트)데이터의 형은 레지스터의 크기와 같다고 간주된다.주의 )오퍼랜드에 레지스터를 포함하지 않은 경우 크기의 지정이 필요예) 한쪽이 간접 번지지정 ,또 한쪽이 숫자의 경우입니다.MOV [BX],12H여기에서 BX 의 값이 10H 라고 합시다.그런데 여기서는1) 10H 번지에 바이트 데이터 12H 를 저정할것인지,2) 10H 번지와 11 번지에 워드 데이터 0012H 를 저장하는 것인지 알수가 없음니다.*.바이트 데이터의 경우 *.워드데이터의 경우번지



번지



+--------+ +---------+ +---------+ +-------+10H
55
12H
12
10H
55
0012H
12
+--------+------> +---------+ +---------+-------> +-------+11H
66

66
11H
66

00
+--------+ +---------
+---------+ +-------+







12H 를 바이트 데이터로써 저장한 경우에는 11H 번지의 내용은 사라지지 않고 남지만12H 를 워드 데이터로써 저장한 경우에는 11H 의 내용은 지워져버립니다.PTR 연사자의 사용--------------------------------------------------------------------------------데이터의 형을 명확하게 하기위하여MOV BYTE PTR [BX],12H ; PTR 은 POINTER 의 약자MOV WORD PTR [BX],12H이와 같이 전송되는 측에 BYTE 또는 WORD 를 지정합니다.이때 PTR 이라는 오버라이트 (overwrite) 연산자와 함께 사용하도록 되어 있읍니다.변수로 선언되어 있는 형이 DB 이든 DW 이든 BYTE , WORD 양쪽다 사용할수가 있읍니다.MOV 명령과 번지지정방식의 정리---------------------------------ADDRESING MODE:*.즉치 방식(immediate mode)AAA EQU 1234H MOV AX,AAA ;메모리의 바이트수가 레지스터바이트 이내일것CS,DS,ES,SS 및 IP,FL 레지스터에 직접 수치를 전송할수는 없읍니다.*.직접 방식(레지스터 번지지정 방식)레지스터의 내용을 직접 전송하는 방식MOV DS,AXMOV CL,BH ; 양쪽의 레지스터의 크기가 일치하는 8비트 혹은 16비트여야 한다.세그먼트 레지스터간의 전송은 할수가 없다 . IP ,FL 레지스터는 사용할수가 없고 ,CS 레지스터로의 값을 전송은 할수 없읍니다.*.간접 방식(메모리 번지지정 방식)전송하는 값이 저장되어 있는 번지를 지정- 방법2가지1) BX,BP,SI,DI 의 4 가지 레지스터와 숫자를 조합시킨다.MOV AX,[BX+DI+4]2) 데이터를 변수로서 정의하고 ,그변수이름을 사용하여 지정하는 경우MOV AX,AAA ; 숫자가 있는 번지에 붙여진 이름을사용하여 간접지정을 하는것간접 방식에서의 번지지정법:+- BX -+ +- SI -+ +- 8비트 숫자 -+
BP
+
DI
+
16비트 숫자
+- 없음 -+ +- 없음 -+ +- 없 음 -+위에서 허용되지 않는 조합방법1) 8비트 숫자만을 사용하는 경우( 번지는 16비트가 아니면 지정할수 없다 )그러나 MOV AX,[1234H] 와 같은 직접 번지지정 방식은 사용할수 없다.직접 메모리 번지를 지정하여 간접 방식을 사용하고 싶을때는 -MOV BX,1234HMOV AX,[BX] ; 와 같이 하지 않으면 안됩니다.2) [BP]를 사용 할수 없다.[BP]를 사용하고 싶을 때에는 [BP + 0 ]를 하면 된다간접지정할때의 주의 사항 :1)명령은 모두 코드 세그먼트에 있다고 본다2)데이터는 데이터 세그먼트 내에 있다고 가정된다.3)BP를 포함하는 간접지정에서는 데이터는 스택 세그먼트 내에 있다고 가정된다.4)프로그램의 처음에서 데이터 세그먼트의 초기설정이 필요 MOV AX,DATA MOV DS,AX ; DATA 를 데이타 세그먼트에 맟춘다. MOV AX,CS MOV DS,AX ; 데이타 세그먼트를 코드세그먼트와 맞춘다.그런데 어떻게 해서라도 데이터 세그먼트 이외의 세그먼트로부터 데이터를 가져오고싶다는 경우 세그먼트 오버라이트 프리픽스(segment overwrite prefix)를 설정,그 명령에 한해서 지정한 세그먼트의 지정한 번지로 부터 데이터를 갖고 오거나,가지고 갈수 있읍니다.예)MOV AX,ES:[BX]MOV CS:[DI+2],CX세그먼트 오버라이트 프리픽스는 다음의 4가지 입니다.CS:,DS:,SS:,ES:MOV 명령으로 전송가능한 조합--------------------------------------------------------------------------------MOV AX,CSMOV DS,AX등 과 같은 형태로 DS <---- CS 를 한 이유는 ,세그먼트 레지스터간의 전송이 허용되지 않기 때문입니다.또한 ,세그먼트 레지스터에는 직접 숫자를 대입 하는 것이 허용되어 있지 않습니다.IP,FL 레지스터는 MOV 명령에서 데이터 전송을 할수 없는 것으로 되어 있읍니다.CS 레지스터에의 데이터의 전송은 허용되지 않습니다.CS 레지스터는 읽어내기만 가능합니다.

asm] 어셈러브 강좌 펌 1

아직도 어셈블리언어가 필요한가.--------------------------------------------------------------------------------어셈블리 언어의 지식은 고속연산 루틴을 작성하기위해서만 필요한 것이 아니라.마이크로 컴퓨터의 시스템을 잘알기 위하여 필요한것이다.메모리상의 데이터나 I/O 기기를 직접 액세스 하는등, 고급언어에서는 할수없는 조작을 할수있다 라는 것이다.CPU 가 이해할수있는 것은 수치로 기술된 명령 밖에 이해 할수가 없읍니다.의사 명령이 확충된 매크로어셈블러:직접기계어로는 번역되지는 않지만 번역 할때 어셈블러에 의해 참조 되는 것입니다.어셈블리 언어란: 기계어와 1 대 1 로 대응된 명령을 기술하는 언어어셈블러란: 어셈블리 언어로 쓰여진 소스를 번역 기계어 프로그램을 작성해주는프로 그램.MASM 은 모듈별 개발이 용이하므로 축적된 소프트웨어를 유효하게 활용 할수있다.MASM 에 의한 어셈블러 개발법 : 아스키 문자열로써 저장하는 형태의 에디터라면 무엇이든 사용 할수있다.링커의 역할:몇가지 의 화일을 합쳐서 하나의 프로그램으로 만드는 것이 링커의 역활이고 링커에 입력이 되는 화일이 중간 화일인 오브젝트 화일 입니다.라이브러리의 사용법:모듈별로 개발된 오브젝트화일 화일 을 합쳐서 하나의 라이브러리 화일 이라는 것을 작성 해둡니다. 링크시에 라이브러리 를 지정하는 것만으로도 그중에서 필요한 오브젝트 화일만을 자동으로 꺼내어져 결합하는 것이 가능합니다.CPU는 기계어를 어떻게 이해하나--------------------------------------------------------------------------------컴파일러 언어: 기계어로의 번역작업을 한꺼번에 합쳐서 수행해 버린뒤에 실행인터프리터 언어:조금씩 번역하면서 실행1 이나 0 의 정보의 양을 1 비트(bit)8비트를 한조로 1바이트(byte)16 비트 CPU 란? :CPU 내의 레지스터가 16비트의 크기,주변장치와 데이터의 교환을 하는 데이터 버스가 16개있다. (16 비트 = 2 바이트 = 1워드 )CPU 의 동작은 2 바이트 를 하나의 단위로 서 실행하고 있어 워드(= 2바이트) 단위로 데이터를 조작 하는 경우의 쪽이 효율이 좋게 되도록 섦계되어 있으므로 효율이 좋은 프로그램을 작성 할때는 이것을 고려 해볼 필요가 있다.특히 ,데이터를 액세스 할때는 0 번지와 1번지 2번지와 3번지 이러한 식으로 짝수 홀수 순으로 조합하여 실행하면 , 한번에 두바이트의 데이터를 읽기 쓰기가 가능하므로 처리의 효율이 향상됩니다.8068 의 레지스터의 구성-------------------------------------------------------------------------------- +---------------+AX:

AH AL
Accumulator Register ---------+ General-purposeBX:
BH BL
Base Register
RegisterCX:
CH CL
Counter Register
DX:
DH DL
Data Register

SP
Stack Pointer

BP
Base Pointer

SI
Source Index

DI
Destination Index (선행 인덱스) -+


IP
Instruction Pointer
FLAGS H,FLAGS L
Flag Register
CS
Code Segment Register ----------+ Segment Register
DS
Data Segment Register

SS
Stack Segment Register

ES
Extra Segment Register -------+ +---------------+*.주의CS:코드세그먼트-CPU가 실행해야 될 명령이 저장되어 있는 세그먼트의 시작을 나타냄SI:소스인덱스 - 번지의 간접지정에 사용 , 특히 스트링명령에 있어서는 메모리로 부터 레지스터로 데이터를 전송하기위한 전송측번지의 지정DI:데스티네이션 인덱스 - 번지의 간접번지에 사용 , 특히 스트링명령에 있어서는 레지스터로 부터 메모리에 데이터를 전송하기위한 수신측 번 지를 지정할때 사용세그먼트의 개념--------------------------------------------------------------------------------8086은 1M 바이트 까지의 메모리를 취급할수가 있음니다.1M바이트는 2의 20승 이므로 번지데이터로서 20비트가 필요하게 되는것입니다.8086레지스터는 16비트 크기 밖에 없으므로 2개의 레지스터를 조합시켜 20비트의 번지를 나타내는 방식을 취한다.예: 2000 H --->세그먼트레지스터+ 3456H ---> 오프셋 IP 나 BX, SI (데이터를 읽고 쓸때) ------ 23456H 오프셋이란 : 어떤 기준 번지로부터의 변위(차이)를 나타낸다. 오프셋 번지는 BX,SI,IP 등의 레지스터에 의해 나타내는것 외에 직접 수치로 지정될수도 있읍니다. 0H +--------+메모리세그먼트 레지스터 ---->20000H--->+--------+

오프셋 번지 ----> 3456H --+--------+-->23456H

물리번지오프셋값만을 지정하면 자동적으로 세그먼트 레지스터의 값은 더하여 계산된다.따라서 세그먼트 레지스터의 값을 한번 설정해놓으면 ,세그먼트 베이스로부터 64KB 이내의 번지는 오프셋 번지를 지정한느것만으로 표시할수있다.세그먼트 레지스터의 용도--------------------------------------------------------------------------------CPU 가 명령을 읽어낼때:CS:IP 의 값으로 부터 물리번지 를 생성 ,그번지로 부터 명령을 꺼낸다.데이터를 전송하는경우:DS: 와 OFFSET (오프셋) 번지 로 부터 데이터가 저장되어있는 물리번지를 계산스택 동작을 수행할때:SS:SP 로부터 스택동작을 수행하는 번지를 계산세그먼트는 서로 전부 혹은 일부가 중복되어도 상관이 없으므로 필요 하다면 몇개의 세그먼트를 같은 물리 번지에 배치 할수도 있음니다.명령의 개략적인 해설--------------------------------------------------------------------------------데이터 전송 명령: MOV사칙연산 명령 : ADD: 덧셈, ADC:덧셈, SUB:뺄셈, SBB:뺄셈 MUL: 곱셈, IMUL:부호달린 곱셈, DIV: 나눗셈, IDIV:부호달린 나눗셈 CBW: 바이트에서 워드로 부호확장 CWD: 워드에서 더블워드로 부호확장 INC: 하나 증가 DEC: 하나 감소논리연산 .쉬프트명령:AND: 논리곱, OR: 논리합, XOR: 배타적 논리합, NOT:부정 ,NEG: 부호반전 SHL: S는 shift ,H는 0을 넣을 것인가 , L 은 left ROR: R은 Rotate,비교분기 명령: CMP, JMP는 무조건 분기, Above(크다),Below(작다.) ,Greater( 부호를 포함해서 크다.) Less(부호를 포함해서 작다) ,Equal( 같다), Not(부정) LOOP: 반복 LOOPE: loop if equal ----+ 조건부 반복 LOOPNE: loop if not equal ---+ CALL: 서브루틴으로 분기 RET: 서브루틴으로 부터 원래의 루틴으로 돌아올 때에스트링 명령: LODS: 메모리로 부터 레지스터에 데이터를 로드 STOS: 메모리에 데이터를 저장하는 명령 LODS, STOS는 메모리의 번지지정 방법이 SI 혹은 DI레지스터를 사용하여 간접지정으로 정해지기 때문에 미리 SI,DI에 번지를 세트해 두어야 한다. LODSB,STOSW,MOVSB,MOVSW: 블럭전송 단독으로 1바이트,1워드의 데이터를 전송 RET(repeat) 명령과 조합시켜 사용 하면 cx 레지스터가 지정 하는 횟수만큼 반복하여 데이터를 전송합니다. 이때 번지는 자동으로 갱신되어가므로 한 명령으로 연속된 여러 데이터를 전송할수가 있읍니다.스트링 명령에는 그 밖에도 데이터의 전송은 하지 않고 레지스터와 메모리의 내용을 비교만 하는 SCAS(scan string), 메모리 끼리의 내용을 비교하는 CMPS(compare string) 이들 명령은 REPE(repeat until equal) REPNE(repeat until not equal)명령과 조합함으로써 일치하는 데이터가 얻어질 때까지 ,혹은 일치하지 않는 데이터가 얻어질 때 까지,메모리상의 데이터를 탐색할수가 있읍니다. SCASB REPE SCASW REPNE CMPSB REPE CMPSWI/O 명령: LSI에 명령을 보낸다든지 데이터를 얻는다든지 하기위한 명령이 I/O 명령 I/O 포트에 데이터를 보내는 명령이 OUT I/O 포트에 데이터를 얻는 명령이 IN 포트의 번호는 직접 수치 혹은 DX 레지스터를 사용하여지정 데이터는 AX 혹은 AL 레지스터를 이용하여 전송인터럽트 명령: INT (interrrupt) 다음에 번호를 지정 인터럽트 처리 루틴으로 부터 원래의 루틴으로 돌아 오려면 IRET(interrupt return)을 사용CPU 제어명령: 주로 8086의 cpu가 수치연산 프로세서 8087과의 사이에서 데이타를 전 송한다든지 주변장치로 부터 READY 신호가 올때까지 실행을 정 지하고 기다린다든지 하기위한 명령입니다. WAIT,ESC,LOCK,HLT : 외부 주기 MOT: 아무수행도 하지 않음그 밖의 명령 : 레지스터 혹은 메모리의 내용을 스택영역으로 대피 복귀시키기 위한 PUSH ,POP , 플래그 레지스터를 스택으로 대피 복귀하는 PUSHF,POPF 두개의 레지스터 혹은 메모리의 데이터를 교환하는 XCHG 한 바이트씩 나열된 데이터의 N 번재 의 것을 꺼내는 XLAT플래그 레지스터를 직접 제어하는 : STC(set carry flag),CLC(clear carry flag), CMC(complement carry flag), STD(set direction flag) ,CLD(clear direction flag), STI(set interrupt-enable flag) CLI(clear interrupt-enable flag) LAHF(load AH from flags ),SAHF(store AH to flags) : 플래그레지스터 하위 8바이트와 AH 레지스터의 데이터를 전송 AAA(ASCII adjust for addition ), DAA(decimal adjust for addition), AAS(ASCII adjust for subtract), DAS(decimal adjust for subtract), AAM(ASCII adjust for multiply ), AAD(ASCII adjust for division) : 플래그 레지스터 하위 8바이트와 AH 레지스터의 데이터를 전송 (이상 모두 오퍼랜드를 갖지 않음) LEA(load effective address):실효번지를 로드 LDS(load data segment register), LES(load extra segment register ): 세그먼트 레지스터를 포함 하는 실효번지를 로드함명령의 구성--------------------------------------------------------------------------------L1: MOV AX,BX ;comment+-----+ +----------+ +-------------+ +-------------+ +----------+
라벨

작동 코드

제 1 오퍼랜드

제 2 오퍼랜드

설명문
+-----+ +----------+ +------+------+ +-------+-----+ +----------+ ^----------------+ 조작의 방향명령에 대해서는제 2오퍼랜드로 부터 제 1 오퍼랜드의 방향으로 조작이 이루어 집니다.L1: 과 같은 명령은 직접적으로 는 기계어 코드로 번역되지 않고 ,분기명령등에서 참조 될때에.번지의 계산에 사용됩니다. 이와 같은 명령을 의사 명령이라고 말하고 ,어셈블리 프로그램을 작성하는데 없어서는 안되는 것입니다.의사명령이란 무엇인가.?--------------------------------------------------------------------------------어셈블러가 소스(source) 프로그래을 기계어 코드로 변환할때에는 필요한 지시를 어셈블러에게 행하는것 입니다.장소(번지)를 지정하는 라벨L1: MOV AX,BX ............ ............ JMP L1 ------> L1 번지로 무조건 뛰라는 명령변수이름은 메모리상의 번지를 지정한다. MOV AX,DATA1----> DATA1 번지에 있는 메모리 워드1234H 를 AX 에 전송하는....... 간접번지 지정방식으로 데이터 전송.......DATA1 DW 1234H
+--------->define word 란 변수정의 의사명령PTR - 데이터의 타입을 나타낸다. BYTE PTRSEGMENT - 세그먼트 이름을 선언 MAIN SEGMENT PARA PUBLIC 'CODE'PUBLIC - 외부 참조 가능임을 나타낸다. PUBLIC PROC1IF - 조건어셈블을 지정 IF IBMPC EQ TRUE ......... ENDIF의사명령에는 절대 필요한것과 그렇지 않은 것이 있다.시스템 호출이란 무엇인가 ?--------------------------------------------------------------------------------입출력을 위한 시스템 호출(system call):시스템에 준비되어 있는 기본 루틴을 사용하기 위한 방법인터럽트와 시스템 호출은 거의 비숫하다.MS-DOS 에서는 주로 인터럽트의 21H 번을 사용 ,그중에서 서브커멘드( subcommand)를 사용한다.시스템호출을 사용하면 프로그램을 효율적으로 개발을 할수가 있다.그러나.주의 사항도 있음니다.1)다른 OS 상으로 이식을 할때에는 그대로 금방 이식할수가 없다2)입출력외의 루틴은 1)독자적으로 작성하든지 2)ROM 내의 루틴을 이용 전자의 경우 프로그램개발에 방대한 시간을 걸린다. 후자의경우 타기종과의 호환성이 사라진다는 문제 점이 있읍니다.그래서 이부분은 어셈블러에 의한 프로그램의 개발에 있어서 큰 문제 입니다.(실수연산을 고급언어에 맡겨 링크 하는 방법등을 생각할수있다.)이러한 문제로 시판되는 소프트웨어 중에서는 직접 BASIC ROM의 루틴 등을 사용하고 있는것이나 특수한 인터럽트 처리를 사용 하고있는것도 있어서 MS-DOS 상에서는 뜨지만 IBM-PC 이외의 기종에서는 동작하지 않는것도 있다.기능의 발달과 범용성의 확대라는 두가지 방향에는 모순되는 측면이있다.어셈블러의 사용법--------------------------------------------------------------------------------오브젝트 화일 이란 : 어셈블의 결과 출력되는 기계어의 중간화일소스 리스팅(source listing): 소스 화일 과 어셈블의 결과 출력된 기계어를 대응시킨 리스트 화일크로스 레퍼런스(cross reference): 라벨이나 변수 이름 이 여기서 정의 되어 어디에 서 참조 되고 있는가를 리스트하는 화일 입니다.링크의 실행--------------------------------------------------------------------------------링커의 역활은 몇개의 오브젝트 화일을 합쳐서 하나의 프로그램으로 한다든지,라이브러리로 부터 필요한 루틴을 꺼내어서 프로그램에 결합하는 것에 있읍니다.오브젝트 모듈 (object module) - 어셈블의 결과 출력되는 오브젝트 화일다른 모듈과 결합 - + 기호를 사용실행화일 (run file ) - 링커에 의해 작성된 실행가능 화일리스트 화일 - 실행가능 화일 중에서 세그먼트나 프로시듀어의 번지나 길이를 나타냄링크의 결과 다음과 같은 메시지가 나오고 링크가 끝납니다.Warning: no STACK segmentThere was 1 error detected스택세그먼트 는 설정하지 않아도 OS 가 자동적으로 설정해 주는 것으로 되어있으므로그대로 실행할수가 있읍니다. ( 다른 에러 를 무시 할수는 없음니다.)COM 화일은 EXE 화일을 변환 하여 만듭니다.EXE2BIN 을 이용 확장자가 .BIN 을 만들고 , 확장자명인 BIN 을 변경하면됩니다EXE 와 COM 화일중 COM 화일이 먼저 실행된다.스택 세그먼트가 선언 되어 있는 EXE 화일은 변환할수 없다.COM 모델과 EXE 모델과는 세그먼트의 초기 설정 등에 차이가 있다디버그의 사용법--------------------------------------------------------------------------------디버그는 프로그램을 조금씩 실행시키면서 레지스터나 메모리의 내용을 살펴 보는 것으로서, 프로그램이 기대한 대로 동작하고 있는가를 살피기 위한 TOOL 입니다.본질적인 알고리즘의 잘못을 찾아내는 것은 쉽지 않지만 어느 부분이 폭주해 버리는 가 라는 것은 알수 있읍니다.EXE 모델과 COM 모델--------------------------------------------------------------------------------EXE 모델은 비교적 큰 프로그램에 COM 은 모델이 비교적 작은 프로그램에 사용 된다MS-DOS 에서는 실행가능 프로그램이 메모리 상에 로드 되었을 때에 프로그램의 직전에PSP(Program Segment Prefix)라고 부르는 부분이 설정되고,그 다음에 프로그램 본체가놓여집니다. PSP 는 전부 100H 바이트가 있어서 프로그램 실행에 필요한 여러가지 정보가 들어있습니다.EXE 모델DS 와 ES 가 PSP 의 시작을CS 가 프로그램의 시작을 나타내도록 세트됩니다.SS 는 특별히 지정하지 않으면 CS 와 같은 값이 됩니다.프로그램의 실행은CS 내의 IP 로 나타내는 번지 부터 시작됩니다.시작번지는 특별히 지정하지 않으면 0임의의 번지 부터 시작할려면 (소스 프로그램의 END 문으로 지정한다.)(주의)DS와 ES 가 PSP 의 부분을 지정하고 있으므로 프로그램 중에서 DS 및 ES 를 사용할때는 반드시 자기가 설정을 다시 하지 않으면 안된다.*.EXE 모델의 세그먼트의 초기치

하위번지+-------------+---->DS,ES
PSP100바이트
+-------------+----->CS,(SS)
프로그램
----->CS:IP(시작번지)상위번지+-------------+

COM 모델COM 화일 을 로드 하였을때 에는 CS,DS,ES,SS 의 4개가 모두 일치하여PSP 의 시작을 지시 하도록 세트됩니다.프로그램의 본체는 100H 바이트의 PSP 직후에 놓여지고 선두로 부터 실행,IP 의 초기치는 100H 로 세트 됩니다.소스프로그램을 작성할때에도 ORG 명령을 사용하여 시작번지를 100H 번지부터설정동시에 프로그램의 시작에 라벨을 붙여서 END문 에 의해서 시작번지를 지정하지 않으면 않됩니다.또한 COM 화일 에서는 세그먼트의 값을 변경하면 안됩니다.*.COM 모델의 세그먼트의 초기치하위번지

+------------+--->CS,DS,ES,SS
PSP100바이트
+------------+--->CS:IP(=100H)
프로그램
시작번지상위번지+------------+

디버그의 실제--------------------------------------------------------------------------------A>DEBUG SAMPLE.EXE_ ------------>디버거의 프롬프트레지스터 내용을 표시하는 R 커멘트역어셈블 U 커멘트실행을 하는 G 커멘트실행 커멘드(GO)의 시작번지는 = 을 사용 _ G=0,F디버거를 끝내는 Q다음 메세지가 나왔을때 한번더 실행을 하려고 하면 폭주해 버린다.Program terminated normally의 메세지가 나오면 일단 디버거를 마친다음 에 다시 처음부터 시작해야 한다.프로그램의 수정법--------------------------------------------------------------------------------디버거를 기동후 화일 을 로드 하는 법: N 커멘드화일을 로드하는 : L 커멘드_NSAMPLE.EXE_L1스텝씩 실행하는 : T 커멘드_T=100,20 20은 20 스텝T 커멘드는 서브루틴이나 인터럽트 처리 루틴의 내부까지 실행그래서 인터럽트 처리 루틴이나 서브루틴을 만났으면그것을 건너 뛸필요가 있음니다.서브루틴을 건너 뛰려면 : G 커멘드_G12F1행을 어셈블 : A 커멘드_A82242:0008 CMP DL,5F2242:000B메모리 내용을 직접 바꿔 써 넣으려면 대치(substitute)명령인: S 커멘드단 한행씩 바꿔쓴 앞뒤의 바이트수가 변화되면 파괴됩니다.수정한 화일을 원래의 디스켓에 써넣으려면 기록(WRITE)명령인: W 커멘드단 실행가능 화일인 EXE 나 COM 화일은 바꾸어 써넣을수가 없읍니다.이것은 디버거가 화일을 메모리상에 로드 할때에 특별한 처리를 하여 실행이 가능한상태로 만들어 놓고 있기 때문입니다.보통은 디스크상의 이미지 (image) 가 그대로 메모리에 상에 로드 되기 때문에 수정하여 다시 써넣을수가 있지만 , 이들화일은 디스크상의 이미지와 메모리 상의 이미지가차이가 있으므로 불가능한 것입니다.

2011년 6월 1일 수요일

망상 6

쏘아진 화살이다.

떠나간 버스다.

한번 뱉은 말은 주워담을 수 없다.

말 조심하자는 말이 많다.

사실 말은 중요한 것이 아니다. 애기가 태어나서 말 못해도 잘 살아 간다.

하지만 세상은 너무 복잡해 졌다.

말이 엄청나게 중요하게 바뀌었다.

오바마가 한마디 하면 몇천명이 죽는다.

오사바 빈 라덴의 한마디가 그랬듯이.

자연의 힘만큼 대단한 것이 사람의 말이 되었다.

우리는 그런 말들을 함부로 하고 산다.

그리고 거짓말도 엄청나게 하고 산다.

LIE TO ME라는 미드가 있는데 사람이 거짓말을 하면 얼굴에 다 표현이 된다는 미국

드라마 이다. 그 드라마를 보면 주변의 얼마나 많은 사람들이 거짓말을 하고 사는지

어렴풋이 보이게 된다.

거짓말은 나쁜 것만은 아니지만... 사람에게 행복을 주지 않는다.

진실하게만 사는 것도 행복을 주지 않는다.

거짓으로 자본주의 사회에 상위 계층으로 간 사람들이 너무도 많기 때문에

그런 것이다.

예를 하나 들어보자.

자신이 좋아하는 사람이 회사에 있다. 하지만 같은 부서의 사람이 옆에 있다.
자신이 좋아하는 사람과 밥을 먹는게 맞지만 옆에 있는 사람과 밥을 같이 먹자고
하는 것 자체가 거짓이고, 거기서 거짓말이 나온다.

하지만 그래야 하는것이 맞을 때가 많다.

어릴 때 배운 예의

그래서 예의가 필요한 것이다.

예의는 대부분 오랜 세월 바뀌어지다가 정형화된 뼈대만 남은 것이다.

친한 사람일수도록 더 예의를 갖춰야 한다.

거짓과 진실의 판단의 기준은.

예를 충분히 갖추었을 때 부터 세어야 한다.

택시도 기본 요금이 있듯이 기본부터 갖추자. 흠.. 이건 별로 감흥이 안 오는군. ^^

그리고 진실은 느껴진다.

망상 5

프랭클린 플래너

있다.

그 외의 플래너 3개는 되는 것 같다.

인터넷에도 플래너는 있다.

구체적이고 자세하게 일년의 계획을 짜는 것도 좋지만.
,
PLAN DO SEE에서

PLAN은 큰 플랜 하나. 그리고 하루하루 PLAN이 중요하다.

물론 하루하루, 일주일, 한달 단위로 짜는 것도 좋다.

나같은 경우 일년동안의 큰 플랜은 결혼이었고

한달의 경우 다이어트 였고.

일주일의 경우 없었고,

하루하루는 늘 머릿속으로 생각한다.

그리고 `늘`이란 단어에 어울리지 않게

일에 치여서 아마 한주중에 반 이상은 아무런 생각없이 살아간다.

그렇다. PLAN DO SEE라는 것을 느끼고 나 역시 많은 변화를 해 보려고 했으나

그렇지 못했다는 것이다.

그래서 뭔가 PLAN DO SEE가 잘 되도록 머리를 굴리고 있다.

뭔가 정해진 것을 만들려고 하고 있다.

정형화된 틀.

결혼은 마음만 있으면 하는 것이지만 결혼식을 통해서 연속적인 시간의 흐름에

상징적인 선이 그여지듯.

뭔가가 필요하다.

망상 4

어제 나의 플랜은 저녁을 안 먹는 것이었다.

그렇게 실행하고 뒤돌아 봤을 때

내일 아침 많이 먹게 되진 않을까?

건강이 많이 해쳐지진 않을까?

내일 저녁은 또 어떻게 해야 하지? 하는 것이 FEEDBACK이었다.

하지만 저녁은 먹지 않았지만.

극심한 스트레스에

맥주 한병을 마셨다.

하지만 안주는 먹지 않았다.

DO 가 완벽하지는 않았지만.

딱 50%+1%는 지켰다고 본다.

그래서 난 행복하게 잤다.

망상 3

사실 말은 번지르르하게 제대로 PLAN을 세우자고 하지만.

우리네 어머니만 봐도 그럴 겨를이 없다.

남편은 변변치 못하지 애들은 말 안 듣지. 돈 때문에 늘 고민하는 사회에

뉴스틀면 국회의원들 싸우지. 그들 나름대로의 신념으로 싸우는데 제대로 된 신념으로

싸우려면 제대로 서로 죽이던지. 그냥 분에 못 이겨서 싸우는 꼴 밖에 안 보이지.

 사실 사람이 던진 돌에 개구리는 맞아 죽는다고. 밤에 술 퍼먹고 돌아 댕기다가 아침에

자기 기분이 나쁘고, 별 생각도 없으면서 다른 당이 미는 신념이 아니꼬와서. 그리고 내

자리는 지켜야 해서 미는 신념이 얼마나 많은 사람들을 죽이고 있는지 그들은 모른다.

 왜 그걸 아냐고? 쇼핑몰에서 보여줬던 오만한 것들을 보니 그 상층의 공기가 어떤지 알 수 있기 때문이다.

이런 넘들 사이에서 그들만의 행복만을 느끼는 것들이 어찌 학생들 공부 한다고 힘들까봐 국수 조금 더 말아 주고 국밥 국물 더 주고 하는 식당 아주머니들의 행복을 위한 PLAN의 시간을 줄까?

 원시 시대로 돌아가서 같이 사냥을 하다가 죽는한이 있어도 지금보다 그 때가 더 행복한 사람이 얼마나 많을까?

 사실 다른 사람 욕할게 아니라. 밥 먹고 사는 것 외에 욕심이 많은 사람들은 다른 사람의 행복을 먹고 자신의 행복을 찾는건 아닌지 1차 적으로 의심해 볼 필요가 있다.

 요즘 시대는 경쟁에서 행복이 많이 온다. 수능 시험 수석, 최고 부자, 이름 올리기는 싫지만 김연아만 봐도 다른 사람과의 경쟁에서 올라선 사람이 행복할거라 생각이 든다. 그렇다면 다른 한편으로는 그들은 다른 사람의 행복을 갉아 먹는 꼴이 된다.

 이런 생각이 바꾸어야 한다. 미국, 유럽 쪽 나라의 사람들이 은/동 메달을 땄을 때 표정을 보았는가? 정말 좋아한다. 하지만 우리나라는 좋아하지 않는다 되려 슬퍼한다.

 왜?

당신이 은/동을 땄을 때 당신 어머니도 슬퍼해야 하는가?

PLAN 조차 생각할 겨를 없이 자식하나만 바라보는 어머니들께 웃는 얼굴을 선물하자.

언론? 이미지? 어머니 보다 중요한가?

사실 우리네 어머니 세대에게 PLAN DO SEE 철학을 보여드리는 것은 힘들다. 한국 사회만 볼 때 해방된지도 얼마 안되었고, 전쟁 겪은 지도 얼마 안되었고. 혼자 잘 살려는 수많은 사람들 사이에서 베이비붐 세대와 그 다음 세대의 생계를 책임 지셨기 때문이다.

그래서 어머니들 PLAN까지도 책임져야 한다.

전화 해서 투정만 부리지 말고, 저는 이제부터 ...을 하려고 합니다. 라고 말하고 매일은 아니더라도 자주 연락해서 나의 PLAN이 실현되는 행복을 내가 잘 느끼고 알려주면 된다.

나의 행복이 곧 당신들의 행복이니까.

쩝.. 정치인 욕을 더 했어야 하는데.

사실 내가 정치인 되어도 욕하는거 별로 신경 안쓸것이기 때문이다.

욕하던 말던~ 나만 잘살면 되지. 가오 잡으면서. ㅋㅋ

망상 2

바야흐로 자 본주의 사회다.

사실 앞으로도 그럴거고. 계속 그럴거다.

자유 민주주의란 말은 어울리지 않는다. 자본주의 사회가 맞다.

돈이 많아도 자살하는 사람 천지지만. 가장 큰 척도를 대라고 하면 돈을 이야기 할 것이다.

돈은 쇳덩어리나 종이 뭉치에 불과하다.

돈이 정말 대표하는 것은 자유이다.

돈이 있음으로 자신이 하고 싶은 것을 할 수 있는 것이다.

만약 돈만 많은 것이 행복의 척도라면, 마더 테레사도 빌 게이츠 보다 불행한 삶인 것이다.

세계 100대 부자도, 이건희가 아무리 잘 살아도 멕시코 통신재벌보다는 행복하지 않으며,

세상에서 가장 힘이 쎈 오바마도 이건희 보다는 불행하다.

 그리고 돈과 관련하여 항상 따라오는 권력이라는 것도 이미 수많은 역사가 증명해 주듯이

행복과 비례하는 것은 아니다. 난 영화를 참 좋아하는데 영화를 보면 다른 사람의 삶을 간접

적으로 살아 볼 수 있다는 점이 그 이유다.

 트로이나 글레디에이터에서 권력의 정점에 서 있는 사람도 항상 불안하고 두려움을 느낀다.

불안감과 두려움은 행복과는 거리가 멀다는 것은 누구나가 알고 있다.

 잠시 딴 곳으로 샜는데 돈에 집중해서 말해야 하겠다.

로또에 담청되서 불행하다는 이야기가 많다. 하지만 당첨된 사람은 전 세계에 엄청나게 많은데 정작 불행한 이야기는 몇 안된다.

 우리 모두는 돈을 어떻게 써야 할지 알고 있으며, 그 돈으로 행복해지는 법을 안다.

하지만 왜 돈이 많은데도 불행해지고 자살하는 경우가 생기는 것일까?

그것은 PLAN DO SEE가 없어서이다.

돈을 많이 번 사람은 우선 PLAN이 사라진다. 왜냐면 돈을 위한 PLAN 이었는데 더 이상 PLAN을 세울수가 없기 때문이다. 그럼 할게 없어진다. 돈만 많고 즐길줄 모른다는 말이다.
돈이 많으면 권력이나 다른데에 관심이 간다. 그런데 그것을 얻지 못하면 불행한 것이다.
이회창(나도 뽑았는데 ㅠ.ㅠ) 이 대통령이 되지 못하고 삐져서 다른 나라로 간 것도 그것과 같다. 사실 이회창 할아버지라고 존칭을 써야 하는데 워낙 유명인사라...
 돈 많고 똑똑해도 자신의 PLAN이 깨지면 행복하지 못하다.

그래서.

PLAN은 큰 것도 있어야 하지만 작은 PLAN도 많아야 한다.

곳곳에는 작은 행복들이 산재해 있다.

제대로 PLAN을 세우는 것이 무엇보다 소중하다.

PLAN DO SEE에 대한 망상 1

매트릭스를 보면서 지금 내가 보는 현실이 진짜가 아니라는 생각도 해 보았다.

비슷한 영화나 만화가 몇개 있는데 제목은 기억나질 않는다.

현실에서는 두뇌만 무수한 선에 연결되어 있고, 그 두뇌는 실재로 자신이 존재한다고

믿고 있다.

 이미 이런 생각들은 수많은 철학가들이 해 보았을 것이다. 데카르트만 해도

나는 생각한다. 고로 나는 존재한다.

고 하지 않았는가? 자신이 생각한다는 것 이외의 모든 것들을 의심해 보라는 말이다.


우선 내가 왜 살고 있는가부터 질문해 본다.

사실 탄생은 내가 원한게 아니었다. 가장 편하고 쉬운 답은 신의 뜻이라고 생각이 된다.

는 것이다. 사실 신이 만든 태양도 제대로 보지를 못하는데 신을 어찌 볼 수 있으며,

내 생각도 잘 모르면서 신의 뜻을 어떻게 알 수 있을까?

신을 믿는 다는 것은 아무런 이유없이 믿어야 한다는 것일 것이다.

가장 편하고 쉬운 답인 것과 동시에 어렵게 자세하게 성의있게 생각해 보아도

내가 탄생한 이유는 알 수가 없다.

 부모님이 낳아주셨으니까.

하지만 난 낳아주셨다는 것에 큰 의미를 두지 않는다. 길러 주셨다는 것에 큰 의미를 둔다.

그리고 어머니의 경우 좀 더 의미를 둔다. 10달동안 배가 아프셨고, 낳을 때 고통이 있으니까.

아버지의 경우에도 걱정하고 어머니 돌봐야 하고 기타 등등이 있지만.

지나보니... 그리고 커보니, 자신의 소유라는 생각이 들 것 같아서 그것은 당연한 일이라고

본다.

소유와 집착은 어떤 것을 가진다는 것에서 같은 의미를 지닌다.

자세한 이야기는 뒤로 하기로 하고.

그렇다면 낳아 주신것과 길러주신것에 보답을 해야 하지 않을까?

내리 사랑이라는 것이 있어서 자신의 자식이 있으면 또 사랑을 그렇게 준다고는 하지만.

하나의 심장을 하나의 대상이라고 보았을 때, 나에게 잘해준 대상이 아닌 다른 대상에게

뭔가를 베푸는 것은 요즘 시대와는 맞지 않다.

왜냐면 과거는 힘든 세월이라서 먹고 살기에도 힘들어서 그렇게 밖에 생을 유지하지 못했지만, 지금은 풍족한 세월이기에 자신이 노력하면 자신의 자식에게도 부모에게도 똑같이 보답을 할 수 있기 때문이다.

그렇게 하지 않아도 된다. 나 역시 효도를 잘 하지 못하는 사람이지만.

살아보면.

정말 아깝지 않은 것은 부모님한테 잘할 때이다.

PLAN 중에 효 라는 것이 하나가 생긴다.

-------------------

왜 태어났냐는 것과 같이.

이유없이 뭔가를 말하고 싶은게 있다.

인간은 행복을 위해 사는 존재이며,

그 행복은 PLAN DO SEE 에서 온다는 것이다.

대학원생의 투고 지도 ④ (완결) — 논문의 수준이란 무엇인가: 사다리와 사분위, 첫 논문 전략

완결편이다. "논문 수준"이라는 말을 해부하고, 에듀테크 석사생의 첫 논문 전략으로 마친다. 학위논문과 학술지 논문은 다른 장르다 먼저 가장 흔한 혼동부터. 학위논문(thesis)은 "내가 연구를 수행할 줄 안다...