1부. 일정 맞추기
   1. 아는 체 하지 마라
   2. 상황을 파악한 다음에 움직여라
   3. 제품-일정-비용 삼각형을 기억하라
   4. 어둠 속으로 돌진하지 마라
   5. 무결점 이정표를 사용하라
   6. 팀워크를 유지하라
   7. 일정에는 조삼모사가 없다
   8. 일정이 밀리면, 전열을 가다듬어라
   9. 밑바닥 기술이 중요하다
   10. 설계할 때는 설계만 한다
   11. 만들어야 출시할 수 있다
   12. 호환성은 카누 만들 때나 필요하다

2부. 위대한 소프트웨어
   13. 고객을 감동시켜라
   14. 통일성이라는 한가지 명제만 기억하라
   15. 설계 사상을 명확하게 잡아라
   16. 비교하라
   17. 균형을 맞춰라
   18. 발전시켜라
   19. 제품을 층층이 쌓아라
   20. 공유할 비전을 정하라

3부. 출시
   21. 팀을 항상 출시 모드로 유지하라

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan
1. 첫 인사

2. 최근 프로젝트 경력에 대한 질문
- 열정이 보입니까?
- 훌륭한 지원자는 상대 수준에 맞춰 설명할 수 있습니다.
- 팀 프로젝트였다면 리더십을 발휘했을 것 같습니까?

3. 답변 불가능한 질문

4. 프로그래밍 문제
- 원래 저장위치에서 문자열을 역순으로 변환하기
- 연결 리스트를 역순으로 만들기
- 한 바이트에서 1인 비트 세기
- 이진 검색
- 문자열에서 '연속적으로 문자가 반복되는 길이'가 가장 긴 부분문자열 찾기
- atoi
- itoa (스택이나 strrev를 서야 하기 때문에 좋은 문제임)
- time complexity, pointer, 변수 명명법, 그림 그리기, 그외 코딩 습관 관찰

5. 만족합니까?
- off-by-one error
- semicolon
- general protection fault

6. 질문 있습니까?
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan
1. 엑셀을 이용하여 아래와 같은 단순한 일정표 작성합니다.

Feature                      Task                       Priority    Orig Est    Curr Est    Elapsed    Remain
Spell Checker            Add Menu Item        1                12              8               8               0
Spell Checker            Main Dialog              1                  8            12               8               4
Spell Checker            Dictionary                 2                  4              4               4               0
Grammar Checker    Add Menu Item        1                16              0               0              16
* Curr Est - Elapsed = Remain

2. 담당 프로그래머만이 제대로 일정을 짤 수 있으며 각 개발자마다 개별 시트를 유지합니다.

3. Task를 세부적으로 나누십시오.

4. Orig과 Curr Est을 동시에 유지하십시오.

5. Elapsed 열은 매일 갱신하십시오.

6. 일정에 휴가나 유일 같은 항목을 넣으십시오.

7. 일정에 디버깅 시간을 넣으십시오.

8. 일정에 통합 (소스코드를 서버에 머지하고 컴파일 오류를 없애는 작업) 시간을 넣으세요.

9. 일정에 여유 기간을 두십시오.

10. 관리자가 프로그래머에게 일정을 단축하도록 절대 강요하지 못하게 하십시오.

11. 일정이 늘어나게되면, 출시를 연기하든지 아니면 몇 가지 쓸모없는 기능을 삭제해야 합니다.
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan
1. 소스코드 관리시스템을 사용하고 있습니까?
2. 한방에 빌드를 만들어낼 수 있습니까?
3. 일일 빌드를 하고 있습니까?
4. 버그 추적시스템을 운영하고 있습니까?
5. 코드를 새로 작성하기 전에 버그를 수정합니까?
6. 일정을 업데이트하고 있습니까?
7. 명세서를 작성하고 있습니까?
8. 조용한 작업 환경에서 일하고 있습니까?
9. 경제적인 범위 내에서 최고 성능의 도구를 사용하고 있습니까?
10. 테스터를 별도로 두고 있습니까?
11. 프로그래머 채용 인터뷰 때 코딩 테스트를 합니까?
12. 무작위 사용편의성 테스트를 수행하고 있습니까?

* 11점 이상은 우수한 성적, 10점 이하는 심각한 문제가 있음
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan
출처: http://www.sunyzero.com


컴파일러가 특정 머신에서 기계어 코드로 변환되어 데이터를 저장하고 가져오는데는 보통 word 단위(4 byte)로 입출력하는 경우가 많다. 이것은 시스템의 효율성을 가져오기 위해서 단위 출력/입력을 하는 것이다. 원래 이렇게 되는 것은 CPU의 특성때문이다. CPU 에서 가장 비용이 많이 들어가는 것은 메모리에 접근하는 작업인데 이 작업이 잦으면 별로 효율적이지 못하게 된다. 따라서 CPU는 (보통 32bit 머신이라면) 주변에 4 byte(32bit)의 데이터 공간을 같이 가져온다. 따라서 1 cycle당 32 bit 단위로 한번에 가져오게 되는 것이다. (항상 32bit는 아니다. 이는 절대적이 아니다.) 이를 컴파일러에서 이용하여 프로그램의 효율을 좋게 하는데, 일부러 데이터를 프로세서가 한번에 접근하는 공간에 단위배수에 맞게 정렬(alignment)하여 데이터를 넣어두면 한번에 딸려오는 뒷 데이터가 있으므로 실제로 메모리에 접근하는 횟수를 줄이고, 효율을 좋게 할 수 있는 것이다. 따라서 컴파일러는 CPU의 이런 설계구조를 통해서 메모리 접근 효율을 좋게 하는 것이다.) 그런데 이런 특성을 컴파일러도 이용하여 속도향상을 가져오게 되는데, 이때 발생하는 문제가 padding이란 것을 포함하여 원래 의도한 바와 다르게 나타나는 구조체의 데이터 크기다. 아래 구조체를 보자.

코드:

typedef struct _MY_ST_A {
char str[10];
char cnt[4];
} MY_ST_A;

typedef struct _MY_ST_B {
char str[10];
int  cnt;
} MY_ST_B;

typedef struct _MY_ST_C {
char str[9];
short cnt;
} MY_ST_C;

typedef struct _MY_ST_D {
char str[10];
double cnt;
} MY_ST_D;

위의 구조체들의 크기(sizeof) 는 어떻게 될까?  사용되는 구조체변수의 주소번지까지 찍어주었다.

코드:

(platform: 32bit machine / solaris)
address / sizeof(MY_ST_A) : 0xffbef3d8 / 14
address / sizeof(MY_ST_B) : 0xffbef3c8 / 16
address / sizeof(MY_ST_C) : 0xffbef3b8 / 12
address / sizeof(MY_ST_D) : 0xffbef3a0 / 24


맨 처음 구조체 녀석(MY_ST_A)은 당연히 char 형 배열 10 byte와 4 byte 가 있으니 sizeof()값이 14 byte 인게 맞다. 근데 두번째 구조체는 보면 16 byte 이다. 이것은 구조체의 두번째 요소가 int 형 (4btye) 이기 때문에 4 byte 기준으로 정렬되므로 4의 배수가 된다. 따라서 모든 요소의 시작은 4 의 배수에서 시작되어야만 한다. 세번째는 short 형(2byte)이므로 2 byte로 정렬되고, double은 8 byte로 정렬되는 것이다. 그러면 그림으로 그려서 보자. MY_ST_A 는 원래 char 형으로 다닥다닥 붙어있으니 머릿속에서 연상도 쉽게 된다. 그래서 두번째와 네번째만 함 그려보자. (편의상 시작 주소는 0x0000 으로 하자.)

코드:

* MY_ST_B 구조체
+----------------+ 0x0000
| char str[0]    | 
+----------------+ 0x0001
| char str[1]    | 
+----------------+ 0x0002
| .............. | 
| .............. | 중간생략(str[2] - str[8] 까지)
| .............. | 
+----------------+ 0x0009
| char str[9]    | 
+----------------+ 0x000a : 아래 2 byte 는 padding 공간이다.
| padding | (4 의 배수중 가장 작은 12으로 맞추기 위해서)
+----------------+ 0x000b | padding | +----------------+ 0x000c : alignment size가 4byte (int형)이므로
| | 4의 배수인 12 byte 부터 int cnt가 시작된다. +--- ----+ 0x000d | | +--- int cnt ----+ 0x000e | | +--- ----+ 0x000f | | +----------------+ 0x0010 => Therefore, sizeof() 값이 16 byte 가 나온다. | .............. |


코드:

* MY_ST_D 구조체
+----------------+ 0x0000
| char str[0]    | 
+----------------+ 0x0001
| char str[1]    | 
+----------------+ 0x0002
| .............. | 
| .............. | 중간생략(str[2] - str[8] 까지)
| .............. | 
+----------------+ 0x0009
| char str[9]    | 
+----------------+ 0x000a : 아래 6 byte 는 padding 공간이다.
| padding | (8 의 배수중 가장 작은 16으로 맞추기 위해서) +----------------+ 0x000b | padding | +----------------+ 0x000c | padding | +----------------+ 0x000d | padding | +----------------+ 0x000e | padding | +----------------+ 0x000f | padding | +----------------+ 0x0010 : alignment size가 8 byte (double형)이므로
| | 8의 배수인 16 byte 부터 double cnt가 시작된다. +--- ----+ 0x0011 | | +--- double ----+ 0x0012 | | +--- cnt ----+ 0x0013 | | +--- ----+ 0x0014 | | +--- ----+ 0x0015 | | +--- ----+ 0x0016 | | +--- ----+ 0x0017 | | +----------------+ 0x0018 => Therefore, sizeof() 값이 24 byte 가 나온다. | .............. |

자 MY_ST_B와 MY_ST_D 와의 차이점이 쉽지 않은가? 가장 큰 alignment 값에 맞추어지게 된다는 것을 보면 쉽게 알 수 있다. 따라서 char 와 int , double 을 섞어서 만들면 가장 큰 double 형에 맞춰져서 구조체 크기가 맞춰진다. 이런 padding 의 원리를 제대로 알고 제대로 구조체를 잡아야만 네트워크를 통해서 데이터를 주고받을때 데이터의 시작 위치가 제대로 맞춰진다. (이런 오류를 피하기 위해서 중간에 아무런 데이터도 없는 char 형을 끼워넣기도 한다.)

코드:

typedef struct _MY_ST_D {
char str[10];
double cnt;
} MY_ST_D;

typedef struct _MY_ST_E {
char str[10];
char filler[6];
double cnt;
} MY_ST_E;

위의 두개의 구조체는 얼핏보기엔 MY_ST_E가 더 커보이지만, 실제 메모리상의 위치하는 크기는 동일하다. 이유는 위에서 입이 닳도록 설명한 padding 위치에 데이터가 들어갔기 때문이다. 그런데 가끔은 이런 padding을 무시하고 싶은 경우도 있을것이다. 따라서 padding을 하지말고 강제로 끼워맞추는 것이 바로 packed 라는 것이다. packed를 이용하면 padding 공간을 무시하고 강제로 데이터를 끼워넣는다. 각 컴파일러마다 다르지만, gcc 에서는 아래와 같이 사용한다.

코드:

typedef struct _MY_ST_D {
char    str[10];
double  cnt;
} __attribute__ ((packed)) MY_ST_D;

혹은
struct _MY_ST_D {
char    str[10];
double  cnt;
} __attribute__ ((packed));

위와 같이 하면 데이터 크기는 18 byte 가 된다. 당연히 padding 공간이었던 6 byte 가 빠져나가기 때문이다. packed 를 하면 데이터가 따닥따닥 붙어서 alignment에 신경쓰지 않아도 되지만, 이는 성능상으로는 안좋기 때문에 별로 쓰라고 권하고 싶지 않다. 따라서 packed 는 특수한 경우(임베디드나 커널 프로그래밍)가 아니면 거의 사용되지 않는다.

* packing 하는 방법
1) source code 내의 특정 struct 에 __attribute__ ((packed)) 지시자를 사용한다.
2) gcc 컴파일시에 --pack-struct 를 써도 같다.

이외에 gcc 에서는 __attribute__ 지시자를 이용해서 alignment 배수를 바꿀 수도 있다. 실제로 아래처럼 char 이지만 4 byte 단위로 데이터를 배열할 수도 있다. 이렇게 하면 위에서는 14 byte 가 나왔지만, 16 byte (4의 배수)가 나온다. 참고로 gcc 에서는 __attribute__ 를 이용해서 많은 것을 바꿀 수 있다.

코드:

typedef struct _MY_ST_A {
char    str[10] __attribute__((aligned(4)));
char    cnt[4];
} MY_ST_A;
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan
From Wikipedia, the free encyclopedia

Saturation arithmetic is a version of arithmetic in which all operations such as addition and multiplication are limited to a fixed range between a minimum and maximum value. If the result of an operation is greater than the maximum it is set ("clamped") to the maximum, while if it is below the minimum it is clamped to the minimum. The name comes from how the value becomes "saturated" once it reaches the extreme values; further additions to a maximum or subtractions from a minimum will not change the result.

For example, if the valid range of values is from -100 to 100, the following operations produce the following values:

  • 60 + 43 = 100
  • (60 + 43) - 150 = -50
  • 43 - 150 = -100
  • 60 + (43 - 150) = -40
  • 10 × 11 = 100
  • 99 × 99 = 100
  • 30 × (5 - 1) = 100
  • 30×5 - 30×1 = 70

As can be seen from these examples, familiar properties like associativity and distributivity fail in saturation arithmetic. This makes it unpleasant to deal with in abstract mathematics, but it has an important role to play in digital hardware and algorithms.

Typically, early computer microprocessors did not implement integer arithmetic operations using saturation arithmetic; instead, they used the easier-to-implement modular arithmetic, in which values exceeding the maximum value "wrap around" to the minimum value, like the hours on a clock passing from 12 to 1. In hardware, modular arithmetic with a minimum of zero and a maximum of 2n can be implemented by simply discarding all but the lowest n bits.

However, although more difficult to implement, saturation arithmetic has numerous practical advantages. The result is as numerically close to the true answer as possible; it's considerably less surprising to get an answer of 127 instead of 130 than to get an answer of -126 instead of 130. It also enables overflow of additions and multiplications to be detected consistently without an overflow bit or excessive computation by simple comparison with the maximum or minimum value (provided the datum is not permitted to take on these values).

Additionally, saturation arithmetic enables efficient algorithms for many problems, particularly in signal processing. For example, adjusting the volume level of a sound signal can result in overflow, and saturation causes significantly less distortion to the sound than wrap-around. In the words of researchers G. A. Constantinides et al:

When adding two numbers using two’s complement representation, overflow results in a ‘wrap-around’ phenomenon. The result can be a catastrophic loss in signal-to-noise ratio in a DSP system. Signals in DSP designs are therefore usually either scaled appropriately to avoid overflow for all but the most extreme input vectors, or produced using saturation arithmetic components.[1]

Saturation arithmetic operations are available on many modern platforms, and in particular was one of the extensions made by the Intel MMX platform, specifically for such signal processing applications.

Saturation arithmetic for integers has also implemented in software for a number of programming languages including C, C++, Eiffel, and most notably Ada, which has built-in support for saturation arithmetic. This helps programmers anticipate and understand the effects of overflow better. On the other hand, saturation is challenging to implement efficiently in software on a machine with only modular arithmetic operations, since simple implementations require branches that create huge pipeline delays.

Although saturation arithmetic is less popular for integer arithmetic in hardware, the IEEE floating-point standard, the most popular abstraction for dealing with approximate real numbers, uses a form of saturation in which overflow is converted into "infinity" or "negative infinity", and any other operation on this result continues to produce the same value. This has the advantage over simple saturation that later operations which decrease the value will not end up producing a "reasonable" result, such as in the computation \sqrt{x^2-y^2}.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan

Binary Arithmetic

Development 2006/12/18 01:26

Table of contents

  • Addition
    • Unsigned
    • Signed
    • Fractions
  • Multiplying
    • Unsigned
    • Signed
    • Fractions

This document will introduce you to the methods for adding and multiplying binary numbers. In each section, the topic is developed by first considering the binary representation of unsigned numbers (which are the easiest to understand), followed by signed numbers and finishing with fractions (the hardest to understand). For the most part we will deal with

Addition

Adding unsigned numbers

Adding unsigned numbers in binary is quite easy. Recall that with 4 bit numbers we can represent numbers from 0 to 15. Addition is done exactly like adding decimal numbers, except that you have only two digits (0 and 1). The only number facts to remember are that

0+0 = 0, with no carry,
1+0 = 1, with no carry,
0+1 = 1, with no carry,
1+1 = 0, and you carry a 1.

so to add the numbers 0610=01102 and 0710=01112 (answer=1310=11012) we can write out the calculation (the results of any carry is shown along the top row, in italics).

Decimal Unsigned Binary
   1  (carry)
   06
  +07
   13
  110  (carry)
  0110
 +0111
  1101

The only difficulty adding unsigned numbers occurs when you add numbers that are too large. Consider 13+5.

Decimal Unsigned Binary
   0 (carry)
   13
  +05
   18
 1101 (carry)
  1101
 +0101
 10010

The result is a 5 bit number. So the carry bit from adding the two most significant bits represents a results that overflows (because the sum is too big to be represented with the same number of bits as the two addends).

Adding signed numbers

Adding signed numbers is not significantly different from adding unsigned numbers. Recall that signed 4 bit numbers (2's complement) can represent numbers between -8 and 7. To see how this addition works, consider three examples.

Decimal Signed Binary
 
   -2
   +3
    1
 1110 (carry)
  1110
 +0011
  0001
Decimal Signed Binary
 
   -5
   +3
   -2
 011  (carry)
  1011
 +0011
  1110
Decimal Signed Binary
 
   -4
   -3
   -7
 1100  (carry)
  1100
 +1101
  1001

In this case the extra carry from the most significant bit has no meaning. With signed numbers there are two ways to get an overflow -- if the result is greater than 7, or less than -8. Let's consider these occurrences now.

Decimal Signed Binary
 
    6
   +3
    9
  110  (carry)
  0110
 +0011
  1001
Decimal Signed Binary
 
   -7
   -3
  -10
 1001 (carry)
  1001
 +1101
  0110

Obviously both of these results are incorrect, but in this case overflow is harder to detect. But you can see that if two numbers with the same sign (either positive or negative) are added and the result has the opposite sign, an overflow has occurred.

Typically DSP's, including the 320C5x, can deal somewhat with this problem by using something called saturation arithmetic, in which results that result in overflow are replaced by either the most positive number (in this case 7) if the overflow is in the positive direction, or by the most negative number (-8) for overflows in the negative direction.


Adding fractions

There is no further difficult in adding two signed fractions, only the interpretation of the results differs. For instance consider addition of two Q3 numbers shown (compare to the example with two 4 bit signed numbers, above).

Decimal Fractional Binary
 
   -0.25
   +0.375
    0.125
 1110 (carry)
  1110
 +0011
  0001
Decimal Fractional Binary
 
   -0.625
   +0.375
   -0.25
  011  (carry)
  1011
 +0011
  1110
Decimal Fractional Binary
 
   -0.5
   -0.375
   -0.875
 1100  (carry)
  1100
 +1101
  1001

If you look carefully at these examples, you'll see that the binary representation and calculations are the same as before, only the decimal representation has changed. This is very useful because it means we can use the same circuitry for addition, regardless of the interpretation of the results.

Even the generation of overflows resulting in error conditions remains unchanged (again compare with above)

Decimal Fractional Binary
 
    0.75
   +0.375
    1.125
 110  (carry)
  0110
 +0011
  1001
Decimal Fractional Binary
 
   -0.875
   -0.375
   -1.25
 1001 (carry)
  1001
 +1101
  0110

Multiplication

Multiplying unsigned numbers

Multiplying unsigned numbers in binary is quite easy. Recall that with 4 bit numbers we can represent numbers from 0 to 15. Multiplication can be performed done exactly as with decimal numbers, except that you have only two digits (0 and 1). The only number facts to remember are that 0*1=0, and 1*1=1 (this is the same as a logical "and").

Multiplication is different than addition in that multiplication of an n bit number by an m bit number results in an n+m bit number. Let's take a look at an example where n=m=4 and the result is 8 bits

Decimal Binary
  10
  x6
  60
     1010
    x0110
     0000
    1010
   1010
 +0000    
  0111100
  

In this case the result was 7 bit, which can be extended to 8 bits by adding a 0 at the left. When multiplying larger numbers, the result will be 8 bits, with the leftmost set to 1, as shown.

Decimal Binary
   13
  x14
  182
     1101
    x1110
     0000
    1101
   1101
 +1101   
 10110110
  

As long as there are n+m bits for the result, there is no chance of overflow. For 2 four bit multiplicands, the largest possible product is 15*15=225, which can be represented in 8 bits.

Multiplying signed numbers

There are many methods to multiply 2's complement numbers. The easiest is to simply find the magnitude of the two multiplicands, multiply these together, and then use the original sign bits to determine the sign of the result. If the multiplicands had the same sign, the result must be positive, if the they had different signs, the result is negative. Multiplication by zero is a special case (the result is always zero, with no sign bit).

Multiplying fractions

As you might expect, the multiplication of fractions can be done in the same way as the multiplication of signed numbers. The magnitudes of the two multiplicands are multiplied, and the sign of the result is determined by the signs of the two multiplicands.

There are a couple of complications involved in using fractions. Although it is almost impossible to get an overflow (since the multiplicands and results usually have magnitude less than one), it is possible to get an overflow by multiplying -1x-1 since the result of this is +1, which cannot be represented by fixed point numbers.

The other difficulty is that multiplying two Q3 numbers, obviously results in a Q6 number, but we have 8 bits in our result (since we are multiplying two 4 bit numbers). This means that we end up with two bits to the left of the decimal point. These are sign extended, so that for positive numbers they are both zero, and for negative numbers they are both one. Consider the case of multiplying -1/2 by -1/2 (using the method from the textbook):

Decimal Fractional Binary
  -0.5
  x0.5 
  -0.25
      1100
     x0100
      0000
     0000
 +111100  
  11110000
 
  

This obviously presents a difficulty if we wanted to store the number in a Q3 result, because if we took just the 4 leftmost bits, we would end up with two sign bits. So what we'd like to do is shift the number to the left by one and then take the 4 leftmost bit. This leaves us with 1110 which is equal to -1/4, as expected.

On a 16 bit DSP two Q15 numbers are multiplied to get a Q30 number with two sign bits. On the 320C50 there are two ways to accomplish this. The first is to use the p-scaler immediately after the multiplier, or the postscaler after the accumulator. to shift the result to the left by one

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan

Barrel shifter

Development 2006/12/17 01:44
From Wikipedia, the free encyclopedia

A barrel shifter is a digital circuit that can shift a data word by any number of bits in a single cycle. It is implemented as a sequence of multiplexors: the output of one MUX is connected to the input of the next MUX in a way that depends on the shift distance. The number of multiplexors required is n*log2(n), where n is the computer's register size. Four common word sizes and the number of multiplexors needed are listed below:
  • 64-bit -- 64 * log2(64) = 64 * 6 = 384
  • 32-bit -- 32 * log2(32) = 32 * 5 = 160
Take for example a four-bit barrel shifter, with inputs A, B, C, and D. The shifter can cyclically after the order of the bits ABCD. That is, it can 'shift' all of the outputs up to three positions to the right (and thus make any cyclic combiation of A, B, C, and D). The barrel shifter has a variety of applications, including being a vital component in microprocessors (alongside the ALU).

The barrel shifter is used in floating-point arithmetic hardware. For a floating-point and or subtract operation, the fractions of the numbers must be aligned, which requires shifting the smaller number (in magnitude) to the right, increasing its exponent, until it matches the exponent of the larger number. This is done by subtracting the exponents, and using the barrel shifter to shift the smaller number to the right by the difference, in one cycle. If a simple shifter were used, shifting by n bit positions would require n clock cycles.

Ref. University of Hamburg's Java Barrel shifter
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan

Perl Resources

Development 2006/10/06 01:19
Perl이라는 언어의 필요성을 느껴 웹에서 구한 resource를 정리해 보았다. 물론 CPAN이나 그외 다른 site에 Perl에 관한 자료가 널려있다는 것을 잘 알고 있다. 이건 다분히 개인적으로 정리를 위한 포스팅이므로 딴지걸지 말길 바란다.

1. Tutorial
http://perltraining.com.au/notes.html
원서를 읽는데 무리가 없다면 가장 추천하는 site이다. 이곳에서 만든 eBook을 다운받을 수도 있고 offline 강의도 들을 수 있다. 물론 offline 강의를 수강하려면 호주에 가야한다. -_-

http://www.scs.leeds.ac.uk/Perl/start.html
구글에서 perl tutorial로 검색하면 첫번째로 찾을 수 있는 site이다. Perl의 간단한 문법 정도를 빠른 시간 내에 숙지할 수 있을만한 양이다. 그러나 Perl의 방대한 문법을 알고 실제로 이용하기에는 그 양이 턱없이 부족한 느낌이다.

http://www.sthomas.net/oldpages/roberts-perl-tutorial.htm
위의 tutorial 보다 더 많은 내용을 담고 있다. 원문은 Robert Pepper가 작성했는데 이 사람과 현재 연락할 수 있는 방법이 없는 듯 하다. 그래서 Steve Thomas가 그의 원문을 대신 web에 publishing하고 있다. 이 tutorial은 400KB가 조금 안되는데 Steve 씨가 매달 2GB의 용량까지만 서비스하기 때문에 언제 보지 못하는 tutorial이 될지 모른다. 이에 Robert 씨의 원문을 http://annyung.net/wiki/index.php/Robert%27s_Perl_Tutorial 에 옮겨 두었다. mediawiki에 그대로 cut'n'paste했기 때문에 원문의 html 파일보다는 많은 장점이 있으리라 생각된다. 물론 오타가 있을 경우 수정도 가능하다. -_-;

2. eBook
http://www.perl.org/books/library.html
실제로 판매되고 있는 책을 eBook으로 다운받을 수 있다. Perl을 처음 접하고 돈이 없다면 이 site에서 "Beginning Perl" 정도는 제본하는게 좋을 듯 싶다.

3. 국내 웹 사이트
http://www.perlmania.or.kr/
http://www.softbrain.co.kr/perl/
http://www.perl.or.kr/
요즘 glue language로 Python이 대세라 그런지 국내 웹 사이트들은 관리가 소홀한 편인 것 같다. 그러나 원서를 보는 것이 부담스럽거나 빠른 습득을 원한다면 국내 사이트를 먼저 들려보는것도 좋을 듯하다.

개인적으로 Perl을 익힐 일은 꿈에도 없을 것이라고 생각했었다. 그러나 내 자의에 의해서가 아니라 누군가 이미 만들어 놓은 Perl 코드를 수정하거나 확인하는 일은 발생하게 된다. 처음엔 "뭐 script 따위가 대충 따라가면 수정할 수 있겠지?"라고 생각했는데  Perl은 그 표현이 너무 풍부해서 자세히 살펴볼 필요가 있는 것 같다.
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan
TAG Perl
1. 디버깅 환경이 열악하다. 특히 JTAG과 T32이 없이 간단한 루틴 만들기도 벅차다.

2. 타겟 보드에 바이너리를 올리는데 생각보다 많은 시간이 소모된다. 그래서 프로그래밍 중 생각의 흐름이 많이 끊긴다.

3. ARM 컴파일러와 링커는 PC에 비해 느리다. 결과 확인하는 시간이 아까워서 더 코딩했다가 꼬이기 시작하면 대략 낭패..

4. 오동작을 보일 때 어쩌면 S/W 문제가 아니라 H/W 문제일 수도 있다. 이를 증명하기 위해서는 oscilloscope로 찍어봐야 하는 번거로움이 생긴다. 그래도 요즘에는 많이 좋아졌다고 한다. 옛날에는 oscilloscope로 디버깅을 했다는 말도 있다. 나처럼 한 번도 oscilloscope를 사용해 보지 못한 사람들은 GND가 어디있는지도 모른다.

5. 사용하는 칩셋은 제품 원가 때문에 항상 변한다. 한 번씩 변할 때 마다 같은 동작을 하는 프로그램도 많은 수정이 필요하다.

6. 혼자서 할 수 있는 건 별로 없다. 간혹 소스 뒤져서 프로그램의 흐름을 파악하는 것 보다 다른 사람한테 물어보는게 더 빠를 수 있다.

7. 점점 Eclipse나 Visual Studio 같은 IDE가 그리워진다.

8. API 문서가 없다. 설마 그런게 있더라도 오래된 버전이다. 이 함수가 무엇을 하는 함수인지 궁금하다면 소스를 보고 한참 생각하던가 누군가에게 물어봐야한다.

9. 납땜도 잘하면 좋다. 간혹 JTAG 연결할 때 필요하다.

10. 퇴근 늦게할 생각하고 느긋하게 코딩하는게 좋다. 조급한 마음을 가지면 어디에서 개발하든 더디게 진행되는데 임베디드 환경에서는 데미지가 더 크다.

11. 그러나 간혹 힘들게 개발했으니 성취감은 두배가 된다고 생각될 때도 있다.

12. Copy & Paste를 하더라도 그 코드 조각에 대해서 이해하려는 마음을 갖자. 아무런 생각없이 코드 조각을 붙였다가 더 고생하는 수가 있다.


그냥 생각나는 대로 몇 자 적어봤습니다. 이 job을 시작한지 얼마 안됐는데 막상 적어놓은 것 보니까 거의 초월의 경지에 이른 사람같네요.. 반성 좀 해야겠습니다.
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan