※CPU스케줄링

1) 정의

- 작업을 처리하기 위해 프로세스들에게 중앙처리 장치나 각종 처리기들 을 할당하기 위한
정책을 계획하는 것

2) 방법별 분류

① 선점(preemptive) 스케쥴링
- 한 프로세스가 CPU를 차지하고 있을 때 우선순위가 높은 다른 프로세스가 현재 프로세
스를 중지시키고 자신이 CPU를 차지할 수 있는 경우
- 높은 우선순위를 가진 프로세스들이 빠른 처리를 요구하는 시스템에서 유용
- 빠른 응답시간을 요구하는 시분할 시스템에 유용
- 높은 우선순위 프로세스들이 들어오는 경우 오버헤드를 초래

② 비선점(nonpreemptive) 스케쥴링
- 한 프로세스가 CPU를 할당받으면 다른 프로세스는 CPU를 점유못함
- 짧은 작업을 수행하는 프로세스가 긴 작업이 종료될 때까지 기다려야 함
- 모든 프로세스들에게 공정하고 응답시간의 예측이 가능

3) CPU 스케쥴링 알고리즘별 분류

① 우선순위(priority) 스케줄링
- nonpreemptive
- 프로세스에게 우선순위를 부여하여 우선순위가 높은 순서대로 처리

ㄱ) 정적(static) 우선순위 방법
- 주변 환경 변화에 적응하지 못하여 실행중 우선순위를 바꾸지 않음, 구현이 쉽고
오버헤드가 적다
ㄴ) 동적(dynamic) 우선순위 방법
- 상황 변화에 적응하여 우선순위를 변경, 구현이 복잡, 오버헤드 많다,
시스템의 응답속도를 증가시켜 효율적

② 기한부(deadline) 스케줄링 - nonpreemptive
- 작업을 명시된 시간이나 기한내에 완료되도록 계획
- 작업시간이나 상황등 정보를 미리 예측하기가 어렵다

③ FIFO 스케줄링 - nonpreemptive
- 프로세스들은 대기 큐에 도착한 순서대로 CPU를 할당 받는다
- 일괄처리 시스템에서 주로 사용, 작업 완료 시간을 예측하기 용이
- 짧은 작업이 긴 작업을 기다리게 됨
- 중요하지 않은 작업이 중요한 작업을 기다리게하여 불합리

④ 라운드로빈(round robin) 스케줄링
- preemptive
- FCFS에 의해서 프로세스들이 보내지며
- 각 프로세스는 같은 크기의 CPU 시간을 할당 받는다
- 시분할 방식에 효과적, 할당시간의 크기가 매우 중요
- 할당시간이 크면 FCFS와 같게되고, 작으면 문맥교환이 자주 일어난다

⑤ SJF(shortest job first) 스케줄링 - nonpreemptive
- 준비큐내의 작업중 수행시간이 가장 짧다고 판단되는 것을 먼저 수행
- FCFS보다 평균 대기 시간을 감소, 큰 작업은 시간 예측이 어렵다
- 짧은 작업에 유리

⑥ SRT(short remaining time) 스케줄링
- preemptive
- 가장 짧은 시간이 소요된다고 판단되는 프로세스를 먼저 수행
- 남은 처리 시간이 더 짧다고 판단는 프로세스가 준비큐에 생기면 언제라도 실행중인
프로세스가 선점됨
- 긴 작업은 SJF보다 대기 시간이 길다

⑦ HRN(highest response ratio next) 스케줄링
- nonpreemptive
- 긴 작업과 짧은 작업간의 지나친 불평등을 어느 정도 보완한 기법
- 짧은 작업이나 대기시간이 긴 작업은 우선순위가 높아진다

⑧ 다단계 큐(multilevel queue) 스케줄링
- preemptive
- 작업들을 여러 종류의 그룹으로 나누어 여러개의 큐를 이용하는 기법

⑨ 다단계 피드백 큐(multilevel feedback queue) 스케줄링
- preemptive
- 입출력 위주와 CPU 위주인 프로세스의 특성에 따라 서로 다른 CPU의 타임 슬라이스를
부여
- 짧은 작업에 유리, 입출력 위주의 작업에 우선권을 줌
- 하위단계 큐일수록 할당시간은 커진다



※프로레스 스케쥴링 기법
1. preemptive 기법(선점 기법)
하나의 프로세스가 CPU를 점유하고 있을 때 다른 프로세스가 CPU를 빼앗을 수 있는 방법.
1) Round Robin 스케줄링: FIFO와 같은 방법이지만, 주어진 시간 할당량 안에 작업을
마쳐야 하며, 할당량을 다 소비하고도 작업이 끝나지 않은 프로세스는 다시 대기 큐의
맨 뒤로 돌아가는 방법.
2) SRT 스케줄링: 실행시간 추정치(남은 시간)가 가장 적은 프로세스에게 먼저
CPU를 할당하는 방법.
3) MFQ(다단계 피드백 큐) 스케줄링: 작업처리를 여러 단계로 나누어 처리하는 기법으로
높은 단계에서는 시간 할당량을 짧게 주고, 낮은 단계로 갈수록 시간 할당량을 많이
주고 마지막 단계는 RR기법으로 처리.

2. non-preemptive 기법(비선점 기법)
프로세스에게 이미 할당된 CPU를 강제로 빼앗을 수 없고, 사용이 끝날 때까지 또는
CPU를 할당 받은 프로세스가 스스로 넘길 때까지 기다려야 하는 방법.
1) FIFO 스케줄링: 대기 큐에 먼저 들어온 작업에게 CPU를 먼저 할당.
2) SJF 스케줄링: 작업 시간이 가장 적은 프로세스에게 CPU를 먼저 할당하는 기법.
3) HRN 스케줄링: 우선 순위에 의한 방법. 

'Embedded Lab > linux, x86' 카테고리의 다른 글

[nask NASM 어셈블러 문법]  (0) 2012.06.07
[NASM과 MASM]  (0) 2012.06.02
[캐리지리턴(\r)]  (0) 2012.05.04
[vi편집기 자동정렬]  (0) 2012.05.01
[rm, rndir 옵션]  (0) 2012.04.11
Posted by cyj4369
,

import java.util.*;
class  inputtest{
    public static void main(String[] args)
    {

Scanner sc=new Scanner(System.in);
     int d;
        System.out.printf("숫자 입력하시오..!  ");
        d = sc.nextInt();
        System.out.printf("입력한 숫자는 %d \n",d);

 }
}

'Development > Java' 카테고리의 다른 글

[아스키코드표]  (0) 2012.04.28
[String형 문장을 이을때는...]  (0) 2012.04.28
[아스키코드 출력]  (0) 2012.04.27
[String에서 한 글자씩 읽기/추출하는 방법]  (0) 2012.04.27
[StringBuffer]  (0) 2012.04.19
Posted by cyj4369
,


Fabien Sanglard's non-blog

  

   


IA-32 assembly on Mac OS X

December 31th, 2009


Introduction


I had to do some low level work with Mac OS X Snow Leopard using my MacBook Pro Core 2 Duo. I learned plenty regarding GAS for i386 and x86_64 but I would not recommend this setup to learn assembly. I think Apple's specifics would discourage a beginner and impair his/her ability to use code samples found in most books. I would rather recommend a IBM T42 with Linux Ubuntu.

EDIT: I've received numerous emails so I'm going to try to explain further. It's legitimate to buy a IA-32 book or to follow an online tutorial about i386 assembly intending to use a MacBookPro to experiment as it should be backward compatible. My concern is that by doing this: Nothing will work ! The code sample won't compile, the libc call won't link and the stack won't be aligned properly. That would be a huge learning curve.


Memory refresh


Just to make sure we are at on the same page, here is a schema of the memory the way I like to represent it:
  • Lower memory at the top.
  • Higher memory at the bottom.
  • Text section contains the actual code.
  • Data section contains initialized global variables (with 0s).
  • Bss section contains uninitialized global variables.
  • Heap grows "down", toward higher address.
  • Stack grows "up", toward lower address.
  • Every function calls, a stack frame is created to hold parameters and local variables.


Registers EAX, EBX, ECX, EDX, Floating Points, MMX's, SSE's are used in operations but logistic is mostly done via ESP and EBP.
More about Stack Frames:

Every time a function is called, a new stack frame is created relying mostly on the EBP and ESP registers.

ESP points to the last item inserted in the stack. EBP points to the base of the current stackframe:
  1. Function parameters are pushed on the stack in reverse order of declaration in source code.
  2. The EIP return address (instruction to start from when the function returns) is pushed on the stack.
  3. The function prolog is:
    • Current EBP value is pushed on the stack.
    • EBP takes the value of the current ESP.
  4. Function's local variable are allocated on the stack in order of declaration.
  5. While in the function body, arguments and local variables are referenced via the EBP register (see schema).
  6. The function epilog is:
    • EBP value is popped from the stack.
    • ESP takes the value of the current EBP.
 void function(int parA, int parB, int parC, int parD)	
 {
   int foo;
   int bar;

   [...]

   return ;
  }


The annoying 16 byte stack alignment


Because compilers try to take advantage of the SIMD unit (MMX,SSE,SSE2 and SSE3 instructions set) Apple want the stack to be 16 byte aligned even in an IA-32 environment, so ESP point to a 0xXXXXXXXC memory address. 

Let's take the example of a small program such as cpuid2.s which goal is to write on screen the type of CPU running, using the libc function printf:

.bss

.data
	output:
	.asciz "The processor Vendor ID is '%s' \n"

	.lcomm buffer, 13


.text

	.globl _main

	_main:

	movl $0, %eax		# define cpuid output option
	cpuid			


	movl $buffer, %edi	# put values in string
	movl %ebx, 0(%edi)
	movl %edx, 4(%edi)
	movl %ecx, 8(%edi)
	movl $0, %ecx
	movl %ecx, 12(%edi)
	
	# Now Calling printf

	subl $0x4, %esp		#padding stack :/ !
	pushl $buffer
	pushl $output
	
	
	
	call _printf		#macosx need libc  pre_
	
				# ESP is at 0xXXXXXXX0 now, 
				# with MacOS X Special stub it will be at 0xXXXXXXXC 
	
	call _exit
	nop
	



Here are three significant stack state at:

  1. Beginning of the program
  2. Just before call _printf
  3. Inside libc's printf



On a "regular" system:


 
On Mac OS X:

 Not only you need to pad the stack but you also need to take into account the fact that Mac OS X will perfom an extra 4 byte push on the stack. That's why with two 4 byte parameters, the stack is only padded with 4 byte so the Mac OS X special still find the stack aligned on 0xXXXXXXXC.

Also on the list of thing to adapt, you need to remember that function parameters are 4 byte further than where they would be because of "Mac OS X"'s special push. For example, the first parameter on regulat system is at 8(%EBP) while it is at 12(%EBP) on Mac OS X.

Compilation problems


An other issue that beginners may find discouraging is that plain old compilation doesn't work. GAS assembly program can normally be compiled via asassembler &ld linker (or gcc directly) via:

	as -o cpuid2.o cpuid2.s
	ld -e _main -o cpuid2 -lc cpuid2.o	

	//or

	gcc cpuid2.s -gstabs -o cpuid2

But this won't work on a MacBookPro Core2 Duo running Snow Leopard, cpuid2.s althought IA-32 valid won't get assembled:

	cpuid2.s:50:suffix or operands invalid for `push'
	cpuid2.s:51:suffix or operands invalid for `push'

It seems as default to x86_64 assembly. You need to be specific about the target architecture:

	
	as -arch i386 -o cpuid2.o cpuid2.s
	ld -e _main -o cpuid2 -lc cpuid2.o	

	//or

	gcc  -arch i386 cpuid2.s -gstabs -o cpuid2


EDIT: Reddit user jah6 pointed out that you can get rid of the alignment problem when compiling with gcc: Use -mstackrealign parameter.

LibC method names


Mac OS S requires yout to prefix all your libc method name with "_". Most code sample in Unix world don't have this constraint.

Recommended reading


Try "Professional Assembly Language", it's a pretty good book. Except that they should really really really stop putting the face of their author on the front cover. What a turn off.



Source code :

I've "ported" a few example from GAS Linux to GAS Mac OS X: cpuid with Write System Calls and cpuid with libc

 

@2009

'Device > Mac' 카테고리의 다른 글

[알아두면 유용한 단축키]  (0) 2012.05.27
[사전에 한영사전 추가하기]  (0) 2012.05.27
[rEFIt삭제하는 방법]  (1) 2012.04.12
[맥북에 오라클 10g 설치하기]  (1) 2011.11.18
[맥에 호스트 등록하는 방법]  (0) 2011.11.17
Posted by cyj4369
,

Call by Value와 Call by Reference

Programming/C/C++ 2010/06/01 23:44


1. value와 reference는 무슨 뜻인가?
먼저, value와 reference를 네이버 영어사전으로 검색해 보겠습니다.

value는 '가치'라는 뜻이 먼저 나오고, 마지막 부분에 "수학용어"로서 '값'이라는 뜻이 있다고 나옵니다.


reference는 '참조'라는 뜻이 많이 쓰이는 편이어서 통합검색부분에 바로 나오는 것 같습니다.

우리가 "지뢰를 모두 안전하게 찾으면 이기는 게임"의 특성을 잘 살려 "지뢰찾기"라고 이름을 짓듯이, 컴퓨터 용어를 지을 때 역시 관련된 특성을 영어로 잘 살리려 할 것입니다. 그래서 Call by Value와 Call by Reference를 알아보기 전에 핵심단어(value와 reference)의 사전적 의미를 알아본 것입니다.
Call by Value는 영어 그대로 값(Value)에 의한(by) 호출(Call)이고, Call by Reference역시 영어 그대로 참조(Reference)에 의한(by) 호출(Call)입니다.

2. Call by Value
Call by Value는 우리말로 "값에 의한 호출"이라는 의미로, 어떤 함수를 호출할 때 전달인자(Parameter)로 데이터 자체를 전달하는 호출 방법입니다.

2.1 스왑함수(Swap Function)의 구현 1
어떤 변수의 값을 서로 바꾸는 작업을 "스왑 한다."라고 합니다. 이는 프로그램을 만들 때 빈번히 일어나는 경우로서, 다음과 같은 작업을 거쳐야 합니다.


사람이야 머리로 두 자료(자료1, 자료2)의 위치를 바꿀 수 있지만, 컴퓨터는 바보(?)라서 임시저장공간이 반드시 있어야 합니다. 위 그림에서 숫자가 매겨진 것이 작업의 순서입니다. 값을 바꿀 자료 두 개(자료1, 자료2)에 대하여

1. "자료1"을 임시저장공간에 복사합니다.
2. "자료2"를 "자료1"에 복사합니다.
3. 임시저장공간에 저장된 "자료1"과 동일한 내용의 자료를 "자료2"에 복사합니다.
4. 필요에 따라 임시저장공간을 제거합니다.

와 같은 작업이 이루어지면 두 자료의 위치가 바뀝니다. 임시저장공간이 있어야 하는 까닭은 2번 과정을 통해 자료1의 내용이 손실되기 때문입니다.
이 내용을 바탕으로 스왑함수를 Call by Value로 구현해보겠습니다.
01./*
02.Call by Value Example 1
03.Programmed by EffortKim
04.*/
05.#include <iostream>
06. 
07.void Swap(int data1, int data2)
08.{
09.int temp;
10. 
11.temp=data1;
12.data1=data2;
13.data2=temp;
14.}
15. 
16.int main()
17.{
18.int a=10, b=20;
19. 
20.std::cout<<"Before\na : "<<a<<", b : "<<b<<std::endl;
21.std::cout<<"Swap Function is called.\n";
22.Swap(a, b);
23.std::cout<<"After\na : "<<a<<", b : "<<b<<std::endl;
24.return 0;
25.}

그럴듯하게 모양이 나오는 것 같습니다. 이 예제는 main함수에 선언된 a와 b의 값을 바꾸기 위하여 Swap함수를 만들고, 이를 전달해 값을 바꾸도록 접근하고 있습니다. 다음은 결과입니다.


아니!!! a와 b의 값이 바뀌어야 하는데, 바뀌고 있지 않습니다.

2.2 Call by Value의 방식
2.1에서 Swap함수를 제대로 구현하지 못했습니다. 위의 결과가 그것을 입증하고 있는데요. 그것은 "Call by Value가 값을 전달하기 때문."이라고 설명할 수 있습니다. 위 예제에서는 변수 a와 b를 바꿀 수 있는 어떤 정보를 주지 않고, a값과 b값 자체를 전달하고 있습니다. 그러므로 a와 b의 값은 바뀌지 않습니다. 즉, Swap함수에서는 변수 a와 b의 값이 아닌, data1과 data2의 값이 교환됩니다. 다음 그림을 보면 이해가 빠를 것입니다.


위 예제에서는 변수 a와 b에 대한 정보(주소값)는 주지 않고 a와 b의 값인 10과 20만 주었습니다. data1과 data2는 "아싸가오리!"라고 외치면서 매개변수로 받았을 것입니다. 그리고 그들(data1과 data2)의 값이 바뀌고 끝이 납니다. 이 때, 변수 a와 b에 대한 정보를 주지 않았으니 변수 a와 b의 값을 교환 하고 싶어도 할 수 없게됩니다. 즉, 교환이 일어나는 메모리 주소는 0x0001과 0x0002가 아닌, 0x0003과 0x0004가 됩니다.
Call by Value는 어떤 함수의 전달인수에 특정 값 자체를 전달하는 방식으로, 특정 값 자체를 전달하다 보니 데이터 자체가 큰 경우 전달하는데 오랜시간이 걸립니다. 대신, 함수의 전달인수로 사용된 데이터 자체는 보호됩니다.
가령, 어떤 무시무시한 악당(갑자기 세균맨이 떠오르네요.)이 위의 스왑함수를 개조하여 스왐함수 내의 data1과 data2에 1을 더하는, 누가 악당 아니랄까봐 정말 악당같은 짓을 행하였습니다. 그래도 data1과 data2의 값만 변할 뿐, main함수 내에 있는 변수 a와 b는 변하지 않습니다.

3. Call by Reference
Call by Value를 통해 Call by Reference에 대해 예측하신 분들이 계셨을 것입니다. Call by Reference는 우리말로 "참조에 의한 호출"로서, 어떤 특정한 값이 아닌 그 값에 대한 정보(이를테면 데이터가 저장된 메모리 번지가 값에 대한 정보라고 할 수 있습니다.)를 전달하는 방식입니다.
2.2의 그림을 이용하자면, Call by Value가 변수 a와 b의 값인 10과 20을 전달했다면, Call by Reference는 변수 a와 b의 메모리 번지인 0x0001과 0x0002를 전달하는 방식이라고 보시면 됩니다.

3.1 스왑함수(Swap Function)의 구현 2
위의 2.1에서 교환되지 않았던 스왑함수를 고쳐보겠습니다.
01./*
02.Call by Reference Example 1
03.Programmed by EffortKim
04.*/
05.#include <iostream>
06. 
07.void Swap(int* data1, int* data2)
08.{
09.int temp;
10. 
11.temp=(*data1);
12.(*data1)=(*data2);
13.(*data2)=temp;
14.}
15. 
16.int main()
17.{
18.int a=10, b=20;
19. 
20.std::cout<<"Before\na : "<<a<<", b : "<<b<<std::endl;
21.std::cout<<"Swap Function is called.\n";
22.Swap(&a, &b);
23.std::cout<<"After\na : "<<a<<", b : "<<b<<std::endl;
24.return 0;
25.}

2.1에서 data1과 data2가 int형이었던 반면, 이번 예제는 int*형이 되었습니다. 먼저 실행 결과 보겠습니다.


우리가 원하는 모양이 되었습니다. Swap함수를 호출하였더니 a와 b의 값이 바뀌었습니다. 아시는 분은 다 아시겠지만, Swap함수에 변수 a와 b 자체를 전달한 것이 아닌, a와 b의 주소값을 전달하여 a와 b에 접근할 수 있도록 하였습니다. 즉, Swap함수 내에서는 data1과 data2의 값을 바꾸는 것이 아닌, data1과 data2가 가리키는 값(a와 b)을 바꾸기 때문에 변수 a와 b의 교환이 일어납니다. 이를 그림으로 표현하면 다음과 같습니다.


우리가 실질적으로 바꾸어야 할 메모리 주소 공간은 0x0001과 0x0002이므로 이 두 주소값을 전달하여 이를 참조(reference)하여 변수 a와 b의 값을 교환할 수 있도록 유도하는 것이 목적입니다.

3.2 C++의 문법 - 레퍼런스(Reference)
사실, 3.2에는 Call by Reference의 방식에 대해 설명하려고 했습니다만, 3.1에서 충분히 설명한 것 같아 C++의 문법 중 하나인 레퍼런스에 대해 설명하겠습니다.
변수이름은 할당된 메모리 공간의 이름과 같습니다. 그래서, 원래는 메모리 주소를 직접 입력하여 메모리에 접근하여야 하지만, 이는 매우 번거롭고 비효율적인 방법이므로, C와 C++는 메모리 공간에 이름을 붙여 이 이름을 부르면 해당 메모리에 접근하도록 하였습니다.
레퍼런스란, 이름을 부여하는 것입니다. 변수를 선언할 때는 메모리 공간을 할당하면서 그 메모리 공간의 이름을 부여하지만, 레퍼런스는 이미 할당된 메모리 공간에 이름만 추가합니다.
쉽게 말해, 어떤 광고에서 어떤 배우가 한 말처럼 "이미 차려진 밥상에 밥숟가락만 얹었을 뿐"에서 밥숟가락이 레퍼런스가 되는 것입니다.
레퍼런스는 이미 할당된 메모리 공간에 대해서만 이름을 추가적으로 부여할 수 있도록 하는 것이기 때문에, 레퍼런스르 선언할 때에는 반드시 변수이름을 대입하도록 합니다. 레퍼런스를 선언할 때에는 &연산자를 사용합니다.
1.// declaration and initialization of variable
2.int a=10;
3.// declaration and initialization of reference
4.int& refa=a;
5.// .......

위 소스코드에서 refa가 레퍼런스입니다. 이 둘을 선언한 다음부터는 a와 refa는 동일한 변수입니다. 이들의 주소값을 조사해도 같은 주소가 나오고, a값이 변하면 refa값도 변합니다.(그 반대도 성립합니다.)
이것을 이용하면, 위의 스왑함수 예제 2(포인터 버전)를 레퍼런스 버전으로 수정할 수 있겠습니다.
01./*
02.Call by Reference Example 2
03.Programmed by EffortKim
04.*/
05.#include <iostream>
06. 
07.void Swap(int& data1, int& data2)
08.{
09.int temp;
10. 
11.temp=data1;
12.data1=data2;
13.data2=temp;
14.}
15. 
16.int main()
17.{
18.int a=10, b=20;
19. 
20.std::cout<<"Before\na : "<<a<<", b : "<<b<<std::endl;
21.std::cout<<"Swap Function is called.\n";
22.Swap(a, b);
23.std::cout<<"After\na : "<<a<<", b : "<<b<<std::endl;
24.return 0;
25.}

레퍼런스는 변수와 동일하므로 포인터와 같이 주소 참조 연산자(*)를 사용하지 않아도 됩니다. 또한, 초기화 할 때 변수 자체를 대입하므로 전달인수로 주소 역참조 연산자(&)를 사용하지 않아도 됩니다. (이 상황에선 사용하면 안됩니다.) 그러므로 소스코드가 포인터 버전에 비하여 깨끗합니다.

3.3 포인터냐!! 레퍼런스냐!! 그것이 문제로다!!!
Call by Reference를 구현할 때 포인터를 사용할 것인지, 레퍼런스를 사용할 것인지 고민하는 경우가 생깁니다. 두가지 방법에 대한 장단점을 소개할 것이니, 이를 보고 스스로 판단 해 보시길 바랍니다.

먼저, 포인터를 이용했을 경우 전달하는 값이 주소값이므로 &연산자를 사용하거나, 포인터를 사용해 인수로 넘겨주어야 합니다. 이를 통해 값의 변경이 있을 것임을 명시적으로 알려주는 셈이 됩니다. 특히, &연산자를 사용하여 변수의 주소를 넘길 경우엔 대놓고 "값을 변경할 것입니다."라고 광고하는 효과를 얻게됩니다. 이렇게 명시적으로 자료의 변경이 있을 것이라고 알려주면 개발자는 이를 보고 에러를 쉽게 찾아내고 디버그 하기가 수월 할 것입니다. 단, 코드가 지저분해지고(주소 참조 연산자, 주소 역참조 연산자를 모두 사용해야 하기 때문입니다.) 할당되지 않은 메모리 공간을 참조할 수 있는 잠재적인 오류가 숨어있습니다.
그리고, 레퍼런스를 이용했을 경우 변수처럼 사용하다 보니, 메모리를 직접적으로 참조하지 않아 할당되지 않은 메모리 공간을 참조할 가능성은 포인터에 비해 줄어듭니다. 코드도 포인터를 사용했을 경우보다는 더 간결해지기도 합니다. 그러나, 어떤 함수의 전달인수로 레퍼런스를 요하는 경우, 그냥 변수 이름만 적어주면 되기 때문에 이 함수가 지금 전달하려는 값을 변경할 것인지, 변경하지 않을 것인지 함수를 해석하기 전에는 알 수 없습니다. 그러므로 변경되면 안되는 변수를 잘못넘겨주어 변경되게 하는 경우에는 속수무책으로 당하기 쉽상입니다. 이런 경우는 대부분 문법적인 오류는 없기 때문에 컴파일러나 링커에 의해서 에러를 찾지는 못하는 경우가 많고, 디버깅을 통해서 알아내야 하는 부분입니다. 또한, 위의 예제에서 Swap(a, b);만 가지고는 이 Swap함수의 전달인수가 레퍼런스인지, 그냥 값인지 알 수 없습니다. 물론,Swap이라는 이름은 값을 변경할 것이라고 알려주긴 하지만, 만일 이름이 Swap이 아닌 Func나 F일 경우에는 선언부나 정의부를 보지 않는이상 값이 변경될 것인지, 변경되지 않을 것인지 알 수 없습니다.

이를 통해 어떤 방법을 써야 할 지 생각해 보셨나요? 위 문제는 Call by Reference에서가 아닌, 어느 경우에나 발생할 수 있는 경우입니다. 그래서 많은 자료에서 위 문제를 많이 언급하고 있습니다. 경우에 따라 좋은 방법을 쓰는 것이 좋겠지요? ^_^ 좋은게 좋은겁니다.

4. 끝마치면서
간략하게 Call by Value와 Call by Reference에 대해 알아보는 시간을 가졌습니다. 이는 매개변수에 값을 전달할 것인가, 값에 대한 참조를 전달할 것인가에 대한 "전달 방법"입니다. 문법적 내용이 아니라는 뜻입니다. 위에서 두 방법을 알아보았을 때 Call by Value와 Call by Reference를 위한 특벌한 문법내용을 언급한 적은 없습니다. 기본적인 문법내용을 토대로 만들어 낸 것입니다. 그러므로 다른 언어(JAVA, C#등)에서도 적용할 수 있는 방법입니다.
단, Viaual Basic에서는 포인터나 그에 상응하는 문법 내용이 없기 때문에 Call by Value와 Call by Reference를 위한 문법이 따로 존재하는 것으로 알고 있습니다. 이에 대한 자세한 정보는 MSDN 페이지인


을 참고하세요.

'Development > C/C++' 카테고리의 다른 글

[LPSTR, LPCSTR, LPTSTR, LPCTSTR , LPWSTR, LPCWSTR 의 의미‎]  (0) 2012.08.19
[C언어 문법: Bit field (콜론 연산자)]  (0) 2012.06.16
[Event]  (0) 2011.12.01
[Semaphore]  (0) 2011.12.01
[Mutex]  (0) 2011.12.01
Posted by cyj4369
,

캐리지 리턴(CR)과 라인 피드(LF)는 느린 프린터의 유산인 걸로 알고 있습니다.
CR은 현재 위치를 나타내는 커서(?)를 맨 앞으로 이동시킨다는 뜻이고,
LF는 커서의 위치를 아랫줄로 이동시킨다는 뜻입니다.
이 두 동작을 합치면 뉴라인('\n')과 동일한 동작을 하게 됩니다.

굳이 두 동작으로 나눈 이유는 과거의 느린 프린터가 물리적인 동작을 취하는데 충분한 시간을 확보해주기 위해서 신호를 두 개로 나누어 보내주었기 때문이라고 알고 있습니다.

하지만 현재는 둘 중 하나만 있어도 뉴라인으로 간주합니다. 따라서 신경쓰지 않으셔도 됩니다. (아~~주 가끔 그 문제로 삽질을 하는 경우도 있을 수는 있지만..- -+)

그리고 LF로 뉴라인을 나타내는지 CR+LF로 뉴라인을 나타내는지는 언어의 차이가 아니라 시스템의 차이입니다.
Unix-like 시스템에서는 LF로,
윈도우즈에서는 CR+LF로 표현합니다.

덧붙이자면,
정규식에서는 CR과 LF는 의미가 없습니다.
모두 뉴라인 하나로 표현됩니다.



printf ("abcdefg\rhi"); 

화면표시결과는 abcdefg 표시후 맨앞줄로 이동후 hi를 표시하면

hicdefg

로 나타나고,

 

printf("abcdefg\nhi");

화면표시결과는 abcdefg 표시후 다음줄로 이동후 hi를 표시하면

abcdefg

             hi

위에서 g 바로밑 다음부터 hi임 (편집기에서 바로보이는지 조금 안맞네요)

 

printf("abcdefg\n\rhi");

는 abcdefg 표시후 커서를 맨앞으로 이동후 줄을 바꾸고 hi를 표시합니다.

abcdefg

hi

로 나타납니다.

'Embedded Lab > linux, x86' 카테고리의 다른 글

[NASM과 MASM]  (0) 2012.06.02
[CPU스케쥴러]  (0) 2012.05.26
[vi편집기 자동정렬]  (0) 2012.05.01
[rm, rndir 옵션]  (0) 2012.04.11
[x86 / datasheet / 메모리관리 / x86에서의 메모리정책 (보호모드/실제모드)]  (0) 2012.04.04
Posted by cyj4369
,

startProject 수행 후 수정하지도 않은 파일에 대해 다음과 같은 에러가 날 수 있다.




startProject로 project1을 만든 후 건들지도 않았던 ../src/geekos/idt.c에서 에러가 발생했다.

이 경우 nasm 어셈블러에 문제가 생긴 경우일 수도 있다. 다시 설치해주자.


















nasm 설치



nasm은 GeekOS 컴파일에 필요한 어셈블러입니다. (홈페이지 : http://www.nasm.us/)
최신버전은 호환성에 문제가 있어 2.08대 버전을 사용해야 합니다. 홈페이지로 들어가 Download 링크를 누른 후, 2.08 디렉토리의 linux 디렉토리에서 nasm-2.08-1.i386.rpm을 다운로드합니다.


설치 패키지를 다운로드 한 후, 우분투에서 설치 가능한 패키지로 변환하기 위해 alien을 사용합니다. alien은 다음 명령어로 설치할 수 있습니다.

sudo apt-get install alien


 alien을 설치했다면, 다음 명령어를 입력하여 다운로드한 *.rpm 패키지를 *.deb 패키지로 변환합니다.

sudo alien -k nasm-2.08-1.i386.rpm

 
 변환이 완료되면 다음과 같이 nasm-2.08-1_i386.deb 파일이 생성됩니다.

 
다음, 생성된 설치 패키지를 설치합니다.

sudo dpkg -i nasm-2.08-1_i386.deb

 

'Development > GeekOS' 카테고리의 다른 글

[startProject하기]  (0) 2012.04.25
[GeekOS 과제를 위한 환경설정]  (0) 2012.03.16
Posted by cyj4369
,

1. visual

ggvG=

gg: 파일의 처음으로
v: visual mode
G: 파일의 끝까지 선택 후
=: 정렬

2. non visual

gg=G

gg: 파일의 처음으로
=: 정렬
G: 끝까지


gg: 파일의 처음으로
G: 파일의 끝으로

Posted by cyj4369
,

[아스키코드표]

참고로 스페이스는 32번...

백스페이스는 8...

 뉴라인(Line Feed)은 10...


'Development > Java' 카테고리의 다른 글

[숫자 입력받기(scanner)]  (0) 2012.05.20
[String형 문장을 이을때는...]  (0) 2012.04.28
[아스키코드 출력]  (0) 2012.04.27
[String에서 한 글자씩 읽기/추출하는 방법]  (0) 2012.04.27
[StringBuffer]  (0) 2012.04.19
Posted by cyj4369
,

본인이 가장 자주 쓰는녀석은 이런 형식이다
String buf = "str";
String plus = buf + "plus";
System.out.println(plus);

근데 포퍼먼스 책에 보니 StringBuffer 를 사용하여
.append(""); 를 사용하라고한다

책에 내용을 보면 문자열 붙이기에서 StringBuffer 는 String보다 수백배 빠르다고한다
느끼지못하는 수백배이겠지만 쌓이다보면 느려진다는것을 느낄지도...

'Development > Java' 카테고리의 다른 글

[숫자 입력받기(scanner)]  (0) 2012.05.20
[아스키코드표]  (0) 2012.04.28
[아스키코드 출력]  (0) 2012.04.27
[String에서 한 글자씩 읽기/추출하는 방법]  (0) 2012.04.27
[StringBuffer]  (0) 2012.04.19
Posted by cyj4369
,

자바로 아스키 코드 (ASCII Code)를 화면에 출력하는 프로그램입니다.

아스키 7번 코드는 삑하는 비프음(Beep)코드이기에, 이 프로그램을 실행하면 삑하는 소리가 나는데, 놀랄 필요 없습니다.

파일명: Foo.java

public class Foo {
  public static void main(String args[]) {

    for (char c = 0; c <= 255; c++)
      System.out.format("%c = 0x%02X (%3d)%n", c, (int) c, (int) c);

  }
}


어떤 문자의 아스키 코드를 얻기 위해서는, 그 문자를 (int) 로 캐스팅한 후, System.out.format()으로 출력하면 됩니다.



실행 결과:


웹에 표현하기 힘든 특수문자들이 많이 나옵니다. 그래서 다음의 코드표는, 키보드로 입력할 수 있는 문자만 표시했습니다.
0x20 등으로 된 것은 16진수이고, 괄호() 안에 든 숫자는 10진수입니다.
참고로, 0x20 은 공백문자 즉 스페이스(Space)의 아스키 코드입니다.
... 생략

  = 0x20 ( 32)
! = 0x21 ( 33)
" = 0x22 ( 34)
# = 0x23 ( 35)
$ = 0x24 ( 36)
% = 0x25 ( 37)
& = 0x26 ( 38)
' = 0x27 ( 39)
( = 0x28 ( 40)
) = 0x29 ( 41)
* = 0x2A ( 42)
+ = 0x2B ( 43)
, = 0x2C ( 44)
- = 0x2D ( 45)
. = 0x2E ( 46)
/ = 0x2F ( 47)
0 = 0x30 ( 48)
1 = 0x31 ( 49)
2 = 0x32 ( 50)
3 = 0x33 ( 51)
4 = 0x34 ( 52)
5 = 0x35 ( 53)
6 = 0x36 ( 54)
7 = 0x37 ( 55)
8 = 0x38 ( 56)
9 = 0x39 ( 57)
: = 0x3A ( 58)
; = 0x3B ( 59)
< = 0x3C ( 60)
= = 0x3D ( 61)
> = 0x3E ( 62)
? = 0x3F ( 63)
@ = 0x40 ( 64)
A = 0x41 ( 65)
B = 0x42 ( 66)
C = 0x43 ( 67)
D = 0x44 ( 68)
E = 0x45 ( 69)
F = 0x46 ( 70)
G = 0x47 ( 71)
H = 0x48 ( 72)
I = 0x49 ( 73)
J = 0x4A ( 74)
K = 0x4B ( 75)
L = 0x4C ( 76)
M = 0x4D ( 77)
N = 0x4E ( 78)
O = 0x4F ( 79)
P = 0x50 ( 80)
Q = 0x51 ( 81)
R = 0x52 ( 82)
S = 0x53 ( 83)
T = 0x54 ( 84)
U = 0x55 ( 85)
V = 0x56 ( 86)
W = 0x57 ( 87)
X = 0x58 ( 88)
Y = 0x59 ( 89)
Z = 0x5A ( 90)
[ = 0x5B ( 91)
\ = 0x5C ( 92)
] = 0x5D ( 93)
^ = 0x5E ( 94)
_ = 0x5F ( 95)
` = 0x60 ( 96)
a = 0x61 ( 97)
b = 0x62 ( 98)
c = 0x63 ( 99)
d = 0x64 (100)
e = 0x65 (101)
f = 0x66 (102)
g = 0x67 (103)
h = 0x68 (104)
i = 0x69 (105)
j = 0x6A (106)
k = 0x6B (107)
l = 0x6C (108)
m = 0x6D (109)
n = 0x6E (110)
o = 0x6F (111)
p = 0x70 (112)
q = 0x71 (113)
r = 0x72 (114)
s = 0x73 (115)
t = 0x74 (116)
u = 0x75 (117)
v = 0x76 (118)
w = 0x77 (119)
x = 0x78 (120)
y = 0x79 (121)
z = 0x7A (122)
{ = 0x7B (123)
| = 0x7C (124)
} = 0x7D (125)
~ = 0x7E (126)

... 생략




자바는 유니코드가 기본이기에, 실은 위의 코드도 유니코드입니다. 그런데 유니코드의 첫부분은 아스키 코드와 똑같기에, 0xFF (=255) 까지만 출력하면 아스키 코드가 나오는 것입니다.

'Development > Java' 카테고리의 다른 글

[아스키코드표]  (0) 2012.04.28
[String형 문장을 이을때는...]  (0) 2012.04.28
[String에서 한 글자씩 읽기/추출하는 방법]  (0) 2012.04.27
[StringBuffer]  (0) 2012.04.19
[static]  (0) 2012.04.19
Posted by cyj4369
,