loop {

  switch(n) {

      case 1 : return 3

      case 2 : return 4

      case 3 : return 5


위와 같이 반복되는 switch문에서

n이 1인 경우와 3인 경우에 값이 반환되는 데 걸리는 시간이 같은거라는 착각이 잠시 들어서

직접 구조를 보기로 했다.


우선 비주얼스튜디오에서 x86어셈블리를 생성해 보았다.



switch(num) {

00D817FC   mov         eax,dword ptr [ebp-8] 

00D817FF   mov         dword ptr [ebp+FFFFFF30h],eax 

00D81805   cmp         dword ptr [ebp+FFFFFF30h],0 

00D8180C   je          00D81822 

00D8180E  cmp         dword ptr [ebp+FFFFFF30h],1 

00D81815   je          00D8182D 

00D81817  cmp         dword ptr [ebp+FFFFFF30h],2 

00D8181E     je          00D81838 

00D81820   jmp         00D81843 

case 0: result++; break;

00D81822     mov         eax,dword ptr [ebp-10h] 

00D81825      add         eax,1 

00D81828      mov         dword ptr [ebp-10h],eax 

00D8182B     jmp         00D8184C 

case 1: result++;break;

00D8182D     mov         eax,dword ptr [ebp-10h] 

00D81830      add         eax,1 

00D81833      mov         dword ptr [ebp-10h],eax 

00D81836      jmp         00D8184C 

case 2: result++;break;

00D81838      mov         eax,dword ptr [ebp-10h] 

00D8183B      add         eax,1 

00D8183E      mov         dword ptr [ebp-10h],eax 

00D81841      jmp         00D8184C 

default: result++;break;

00D81843      mov         eax,dword ptr [ebp-10h] 

00D81846     add         eax,1 

00D81849     mov         dword ptr [ebp-10h],eax 

}


return 0;

00D8184C      xor         eax,eax 

}



if - else 문을 썼을 때 처럼

num의 값과 case에 있는 값들을 윗쪽부터 차례차례 비교해나간다는 것을 볼 수 있다.




이번에는 액션스크립트 바이트코드를 보자.

다음과 같은 코드를 작성하고 flex sdk에 포함되어 있는 swfdump로 바이트코드를 생성했다.


    D0                       getlocal0    

    30                       pushscope    

    D0                       getlocal0    

    24 01                    pushbyte       1

    68 03                    initproperty   :n

    10 28 00 00              jump           L0


    09                   L1: label        

    D0                       getlocal0    

    24 11                    pushbyte       17

    68 05                    initproperty   :m

    10 68 00 00              jump           L2


    09                   L3: label        

    D0                       getlocal0    

    24 12                    pushbyte       18

    68 05                    initproperty   :m

    10 5E 00 00              jump           L2


    09                   L4: label        

    D0                       getlocal0    

    24 13                    pushbyte       19

    68 05                    initproperty   :m

    10 54 00 00              jump           L2


    09                   L5: label        

    D0                       getlocal0    

    24 14                    pushbyte       20

    68 05                    initproperty   :m

    10 4A 00 00              jump           L2


    D0                   L0: getlocal0    

    66 03                    getproperty   :n

    D5                       setlocal1    

    24 00                    pushbyte       0

    D1                       getlocal1    

    1A 06 00 00              ifstrictne     L6

    24 00                    pushbyte       0

    10 26 00 00              jump           L7


    24 01                L6: pushbyte       1

    D1                       getlocal1    

    1A 06 00 00              ifstrictne     L8

    24 01                    pushbyte       1

    10 19 00 00              jump           L7


    24 02                L8: pushbyte       2

    D1                       getlocal1    

    1A 06 00 00              ifstrictne     L9

    24 02                    pushbyte       2

    10 0C 00 00              jump           L7


    10 06 00 00          L9: jump           L10

    24 03                    pushbyte       3

    10 02 00 00              jump           L7


    24 03                L10:pushbyte       3

    08 01                L7: kill           1

    1B BD FF FF 03 9F FF FF A9 FF FF B3 FF FF BD FF FF  

   lookupswitch   default:L5 maxcase:3 L1 L3 L4 L5

    47                   L2: returnvoid  


예를 들어 A9로 점프하라는 명령이 있으면 L3 : 붙은 곳으로 점프되는 것이다.


코드를 보면, 우선 변수들을 초기화하고 L0으로 점프한다.

그리고 스택에 0을 넣고 ifstrictne명령으로 n과 0을 비교하는 연산을 수행한다.

스택에 들어있는 두 값이 다르면 점프를 하고 같으면 점프하지 않고 다음 인스트럭션을 실행한다.


여기서는 n이 1이므로 L6으로 점프하게 된다.

L6의 ifstrictne에선 값이 같다고 판단되므로 L8로 점프하지 않고 그냥 통과하여

jump 명령에 의해 L7로 점프한다.

여기서 점프하기 전에 스택에 1을 넣어두는데

이 값이 L7의  lookupswitch에서 어디로 분기할지를 결정하게 된다.


이 코드의 lookupswitch에서는 스택에 0이 있을 때 9F FF FF 만큼 점프하고,

1이 있을 때는 A9 FF FF만큼 점프한다. (2의 보수로 음수를 표현한 형태임)

A9 FF FF만큼 점프한 위치에는 L3이 있는데 이 부분의 인스트럭션부터 다시 아래로 실행을 시작한다.


L3으로 가 보면 m에 18을 대압하는 것을 볼 수 있다.

최종적으로는 L2로 점프하여 실행을 마친다.


===========================================================================













Adobe Flash Professional CS5 버전에서 CS5.5, CS6, CC로 제작된 fla파일을 열려고 하면 열 수 없다는 오류가 뜨는데,

Flannel이라는 프로그램을 쓰면 그런 상위버전의 fla파일들을 CS5에서 열 수 있다.

http://ajarproductions.com/blog/2012/03/06/flannel-open-newer-fla-files/

공식 블로그에서 바로 다운받을 수 있게 되어있다.




Adobe AIR로 만들어진 프로그램인데 사용방법은 매우 간단하다.

바꿀 파일을 Flannel안으로 드래그하면 끝.






이렇게 잘 열린다!!










===========================================================================================







플래시디벨롭에서 아래와 같은 식을 입력하면


num = (a+b)*(c+b);

num = a*sin(c) + b*cos(d);



세미콜론으로 문장을 마치거나 엔터로 줄바꿈을 하는 순간 이렇게 변해버린다.


num = (a + b) * (c + b);

num = a * sin(c) + b * cos(d);


개인의 선호도에 따라 이런 자동 띄어쓰기가 상당히 거슬릴 수도 있는데

설정창에서 이것을 해제할 수 있다.


Tools메뉴에서 Program Settings에 들어간다.



위 사진에서처럼 ASCompletion항목을 클릭해서

Helpers에 있는 Characters Requiring Whitespace를 확인하고 연산자들을 지운다.

(잘못 지웠을 때를 대비해 어떤 연산자들이 있었는지 기억해 두면 좋을 것이다...)

이 때 = 만 남기고 +를 지운다든지 하면

+= 연산자를 사용했을 때 간격이 떨어져서 + = 가 돼버릴 수 있으니 주의해야 한다.


설정을 마치면 연산자 양 옆에 더 이상 자동으로 간격이 벌어지지 않는다.












▼이곳에 플래시가 삽입되어 있습니다. 




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package kr.tibyte
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.geom.Vector3D;
     
    /**
     * ...
     * @author
     */
    public class Main extends Sprite
    {
         
        [Embed(source="../../sample1.png")]
        private var SampleImage1:Class;
        [Embed(source="../../sample2.png")]
        private var SampleImage2:Class;
         
        private var _bitmaps:Vector.<Bitmap> = new Vector.<Bitmap>(IMG_NUM);
        private var _imgArr:Vector.<Sprite> = new Vector.<Sprite>(IMG_NUM);
        private var _imgWidth:int = 120;
        private var _imgHeight:int = 80;
        private var _r:Number; //회전반경
        private var _yaw:Number = 0;
        private var _container:Sprite = new Sprite();
         
        private const IMG_NUM:int = 6;
        private const THETA:Number = 0.003*3/180*Math.PI; //회전각속도
        private const MARGIN:int = 20; //이미지 간격
         
        public function Main():void
        {
             
            for (var i:int = 0; i<IMG_NUM; i++)
            {
                if (Math.random()>0.6)
                    _bitmaps[i] = new SampleImage1();
                else
                    _bitmaps[i] = new SampleImage2();
                 
                _bitmaps[i].x = -_bitmaps[i].width/2-MARGIN;
                _bitmaps[i].y = -_bitmaps[i].height/2;
                _imgArr[i] = new Sprite();
                _imgArr[i].addChild(_bitmaps[i]);
                _imgArr[i].width = _imgWidth;
                _imgArr[i].height = _imgHeight;
                _container.addChild(_imgArr[i]);
            }
            //회전반경을 이미지크기+마진값에 딱 맞게 설정
            _r = (_imgWidth+2*MARGIN)/(2*Math.tan(Math.PI/IMG_NUM));
             
            _container.x = 200;
            _container.y = 150;
            this.transform.perspectiveProjection.projectionCenter = new Point(_container.x, _container.y);
            addChild(_container);
             
            stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
        }
         
        private function mouseMoveHandler($evt:MouseEvent):void
        {
             
            var old:Point = this.transform.perspectiveProjection.projectionCenter;
            old.y = stage.mouseY;
            root.transform.perspectiveProjection.projectionCenter = old;
         
        }
         
        private function enterFrameHandler($evt:Event):void
        {
             
            //마우스로 회전제어
            _yaw += THETA*(stage.mouseX-stage.stageWidth/2);
             
            display();
         
        }
         
 
         
        private function display():void
        {
            var angle:Number;
            for (var i:int = 0; i<IMG_NUM; i++)
            {
                angle = _yaw+i*2*Math.PI/IMG_NUM;
                _imgArr[i].x = _r*Math.cos(angle);
                _imgArr[i].z = _r*Math.sin(angle);
                 
                //angle과 수직이 되도록 rotationY 를 설정
                _imgArr[i].rotationY = (180/Math.PI)*-1*(Math.PI/2+angle);
                 
                 
                /* //rotationY 대신 transform속성으로 회전하기
                   _imgArr[i].transform.matrix3D.pointAt(new Vector3D(),Vector3D.Z_AXIS, new Vector3D(0, -1, 0));
                 */
            }
             
            //다시 그리기
            var seq:Vector.<int> = genSequence(IMG_NUM);
            seq.sort(compare);
             
            _container.removeChildren();
            for (i = 0; i<IMG_NUM; i++)
            {
                _container.addChild(_imgArr[seq[i]]);
            }
         
             
            //z소팅을 위한 비교함수
            function compare($a:int, $b:int):Number
            {
                if (_imgArr[$a].z>_imgArr[$b].z)
                    return -1;
                else if (_imgArr[$a].z==_imgArr[$b].z)
                    return 0;
                else
                    return 1;
            }
        }
 
         
        private function genSequence($n:int):Vector.<int>
        {
            var arr:Vector.<int> = new Vector.<int>($n);
            for (var i:int = 0; i<$n; i++) {
                arr[i] = i;
            }
            return arr.concat();
        }
    }
}







플래시디벨롭을 설치하고 한글을 쳐보니 네모가 마구 쏟아진다.

인코딩을 UTF-8로 하고 한글폰트를 써도 깨지길래

한시간가량 구글링을 하며 별 설정을 다 건드려봐도,

다른 버전으로 재설치를 계속 해봐도 여전히 깨져서 나오는 한글..

자포자기하는 심정으로 컴퓨터를 재부팅했는데 거짓말처럼 한글이 제대로 나오기 시작한다


***

윈도를 재설치하고 시스템 로켈을 한국어로 해보고 레지스트리 추가 등 별걸 다해봐도

불규칙적으로 영문폰트의 한글이 깨지는 현상이 계속 발생한다..

원인을 못찾아서 그 문제가 생기면 그냥 로그오프 후 로그온 중...






=======================================================================



액션스크립트3.0으로 만든 RGB큐브.



(▼여기에 플래시가 삽입되어 있습니다)




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import flash.display.Shape;
import flash.geom.Vector3D;
import flash.geom.Matrix3D;
import flash.events.MouseEvent;
 
var scale:int = 160;
var density:int = 10;
var densityCube:int = density*density*density;
var points:Vector.<Shape> = new Vector.<Shape>(densityCube);
var pointsPosition:Vector.<Vector3D> = new Vector.<Vector3D>(densityCube);
var centralPoint:Vector3D = new Vector3D(stage.stageWidth/2, stage.stageHeight/2, scale/2);
var angleSpd:Number = 0;
var mouseAngle:Number = 0;
var mouseDistance:Number = 0;
var mouseSin:Number = 0;
var mouseCos:Number = 1;
 
for(var i_z:int=0; i_z<density; i_z++) {
    for(var i_y:int=0; i_y<density; i_y++) {
        for(var i_x:int=0; i_x<density; i_x++) {
            var index:int = density*density*i_z+density*i_y+i_x;
            var color:uint = int(i_z/density*256)<<16|int(i_y/density*256)<<8|int(i_x/density*256);
            points[index] = new Shape();
            points[index].graphics.beginFill(color);
            points[index].graphics.drawRect(0,0,4,4);
            points[index].graphics.endFill();
             
            pointsPosition[index] = new Vector3D();
            pointsPosition[index].x = centralPoint.x-scale/2 + i_x*scale/(density-1);
            pointsPosition[index].y = centralPoint.y-scale/2 + i_y*scale/(density-1);
            pointsPosition[index].z = centralPoint.z-scale/2 + i_z*scale/(density-1);
             
            points[index].x = pointsPosition[index].x;
            points[index].y = pointsPosition[index].y;
            points[index].z = pointsPosition[index].z;
            addChild(points[index]);
        }
    }
}
 
 
stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
function enterFrameHandler(evt:Event):void
{
    for(var index:int=0; index<densityCube; index++) {
        pointsPosition[index].x -= centralPoint.x;
        pointsPosition[index].y -= centralPoint.y;
        pointsPosition[index].z -= centralPoint.z;
         
        var old:Vector3D = new Vector3D(pointsPosition[index].x, pointsPosition[index].y, pointsPosition[index].z);
        pointsPosition[index].y = Math.cos(angleSpd*mouseSin)*old.y - Math.sin(angleSpd*mouseSin)*old.z;
        pointsPosition[index].z = Math.sin(angleSpd*mouseSin)*old.y + Math.cos(angleSpd*mouseSin)*old.z;
        old.x=pointsPosition[index].x; old.y=pointsPosition[index].y; old.z=pointsPosition[index].z;
        pointsPosition[index].x = Math.cos(angleSpd*mouseCos)*old.x - Math.sin(angleSpd*mouseCos)*old.z;
        pointsPosition[index].z = Math.sin(angleSpd*mouseCos)*old.x + Math.cos(angleSpd*mouseCos)*old.z;
     
        pointsPosition[index].x += centralPoint.x;
        pointsPosition[index].y += centralPoint.y;
        pointsPosition[index].z += centralPoint.z;
         
        points[index].x = pointsPosition[index].x;
        points[index].y = pointsPosition[index].y;
        points[index].z = pointsPosition[index].z;
    }
 
}
 
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
function mouseMoveHandler(evt:MouseEvent):void
{
    var dx:Number = stage.mouseX-stage.stageWidth/2;
    var dy:Number = stage.mouseY-stage.stageHeight/2;
    mouseDistance = Math.sqrt(dx*dx+dy*dy);
    mouseCos = dx/mouseDistance;