반응형

1. 시간

테스트 1 〉	통과 (0.29ms, 88.9MB)
테스트 2 〉	통과 (0.92ms, 76.1MB)
테스트 3 〉	통과 (0.32ms, 72.6MB)
테스트 4 〉	통과 (3.35ms, 78.8MB)
테스트 5 〉	통과 (0.24ms, 85.9MB)
테스트 6 〉	통과 (0.26ms, 78.8MB)
테스트 7 〉	통과 (0.93ms, 80.9MB)
테스트 8 〉	통과 (0.30ms, 82.3MB)
테스트 9 〉	통과 (0.79ms, 85.7MB)
테스트 10 〉	통과 (1.31ms, 74.6MB)
테스트 11 〉	통과 (1.44ms, 76.6MB)
테스트 12 〉	통과 (0.22ms, 85MB)
테스트 13 〉	통과 (0.66ms, 79.8MB)

2. 풀이

합집합, 교집합을 구하면 되는 문제인데, 처음엔 Set을 이용할까 했다.

but,

A = {1, 1, 2, 2, 3}, 다중집합 B = {1, 2, 2, 4, 5}라고 하면, 교집합 A ∩ B = {1, 2, 2}, 합집합 A ∪ B = {1, 1, 2, 2, 3, 4, 5}

이렇게 해야 한다. 그래서 Map을 이용했다.

A의 다중 집합, B의 다중 집합을 Map<String, Integer>에 저장했다.

  • key: 두글자
  • value: 개수
  1. 합집합 구하기

합집합 Map<String, Integer> temp;

A의 다중 집합에 있는 특정 String의 개수랑 B의 다중 집합에 있는 특정 String 개수의 최대치를 저장하면 된다.

temp[”find”]=Math.max(A[”find”],B[”find”])
  1. 교집합 구하기

교집합의 경우는 반대로, 최소치를 저장하면 된다.

temp[”find”]=Math.min(A[”find”],B[”find”])

3. 코드

⭕ 정답

import java.util.*;

class Solution {
    
    HashMap<String, Integer> A, B, hap, cross;
    
    public int solution(String str1, String str2) {
        A=new HashMap<>();
        B=new HashMap<>();
        hap=new HashMap<>();
        cross=new HashMap<>();
        
        A=count(str1);
        B=count(str2);
        
        int cro=getCross();
        int h=getHap();
        
        if(cro==h) return 65536;
        
        long value=cro*65536;
        int answer = (int) (value/h);
        
        return answer;
    }
    
    public int getCross(){
        HashMap<String, Integer> temp=new HashMap<>();
        
        for(Map.Entry<String, Integer> entry : A.entrySet()){
            String s=entry.getKey();
            int cnt=entry.getValue();
            
            temp.put(s, Math.min(A.get(s), B.getOrDefault(s,0)));
        }
        
        int ans=0;
        for(Map.Entry<String, Integer> entry : temp.entrySet()){
            ans+=entry.getValue();
        }
        
        return ans;
    }
    
    public int getHap(){
        HashMap<String, Integer> temp=new HashMap<>();
        
        for(Map.Entry<String, Integer> entry : A.entrySet()){
            String s=entry.getKey();
            int cnt=entry.getValue();
            
            temp.put(s, Math.max(A.get(s), temp.getOrDefault(s,0)));
        }
        
        for(Map.Entry<String, Integer> entry : B.entrySet()){
            String s=entry.getKey();
            int cnt=entry.getValue();
            
            temp.put(s, Math.max(B.get(s), temp.getOrDefault(s,0)));
        }
        
        int ans=0;
        for(Map.Entry<String, Integer> entry : temp.entrySet()){
            ans+=entry.getValue();
        }
        
        System.out.println(ans);
        
        return ans;
    }
    
    public HashMap<String, Integer> count(String str){
        int sz=str.length();
        HashMap<String, Integer> t=new HashMap<>();
        
        for(int i=0;i<sz-1;i++){
            StringBuilder s=new StringBuilder();
            for(int j=0;j<2;j++){
                char c=str.charAt(i+j);
                if(c>='A'&&c<='Z'||c>='a'&&c<='z'){
                    s.append(c);
                }
                else break;
            }
            
            if(s.length()==2){
                String temp=new String(s).toLowerCase();
                t.put(temp, t.getOrDefault(temp,0)+1);
            }
        }
        
        return t;
    }
    
}
반응형

'computer language > JAVA 문제풀이' 카테고리의 다른 글

[JAVA] 프로그래머스 - 튜플  (0) 2026.02.15
[Java] 2019 KAKAO BLIND - 후보키  (0) 2026.02.11
반응형

링크

https://school.programmers.co.kr/learn/courses/30/lessons/64065

1. 시간

테스트 1 〉	통과 (0.73ms, 82MB)
테스트 2 〉	통과 (0.63ms, 77.6MB)
테스트 3 〉	통과 (0.65ms, 96.5MB)
테스트 4 〉	통과 (1.14ms, 84.6MB)
테스트 5 〉	통과 (2.64ms, 78.7MB)
테스트 6 〉	통과 (3.85ms, 82.3MB)
테스트 7 〉	통과 (31.52ms, 76.7MB)
테스트 8 〉	통과 (49.23ms, 90.2MB)
테스트 9 〉	통과 (51.67ms, 101MB)
테스트 10 〉	통과 (62.25ms, 87.4MB)
테스트 11 〉	통과 (68.06ms, 94.6MB)
테스트 12 〉	통과 (97.66ms, 100MB)
테스트 13 〉	통과 (101.94ms, 126MB)
테스트 14 〉	통과 (94.41ms, 117MB)
테스트 15 〉	통과 (0.61ms, 75.5MB)

2. 풀이

카카오 문제는 입력부터가 쉽지 않다. 일단 입력 부분에서 한번 꼬는 건 기본인 것 같다.

입력 예시: "{{2},{2,1},{2,1,3},{2,1,3,4}}”

일단 고려할 사항

  1. 로직
  2. 입력

로직

로직은 쉬웠다. 각 괄호 안의 숫자들의 개수에 따라 정렬하고, 순차적으로 탐색한다.

없는 원소일 경우 그 원소의 다음 번호를 부여하면 되는 방식이다.

예를 들어, 입력이 이렇게 있을 경우

더보기
더보기

"{{4,2,3},{3},{2,3,4,1},{2,3}}”

튜플이 (3,2,4,1)이다.

그 이유는,

더보기
더보기

(a1, a2, a3, ..., an) 튜플의 집합은 {{a1}, {a1, a2}, {a1, a2, a3}, {a1, a2, a3, a4}, ... {a1, a2, a3, a4, ..., an}}

이기 때문에, {3}이 있으므로 3이 튜플의 가장 첫번째 원소여야 한다. 그 다음 {2,3}에서 3은 이미 첫번째 원소이기 때문에 2는 2번째 원소가 된다. 즉, 집합의 길이별 오름차순 정렬을 먼저 해주고, 각 집합의 원소 중 번호가 부여 안된 원소가 있다면 번호를 부여하면 된다. (번호가 몇번째 원소인지)

이건 HashMap으로 처리해줬다.

입력

솔직히 입력 어떻게 해야하는지 생각한게 더 오래 걸렸다.

더보기
더보기

"{{4,2,3},{3},{2,3,4,1},{2,3}}”

split으로 하려고 했는데, 집합 안에도 ,가 있어서 제대로 안나올 것 같았다.

그래서 스택으로 괄호 문제 했던 것처럼,

입력을 순차 탐색해서

  1. {가 나올 경우, 집합의 원소를 담을 ArrayList 생성
  2. }가 나올 경우, ArrayList를 저장
  3. ,가 나올 경우, 앞의 문자를 숫자로 변환해 ArrayList에 저장
  4. 숫자가 나올 경우, StringBuilder에 추가

3. 코드

⭕ 정답

import java.util.*;

class Solution {
    
    ArrayList<ArrayList<Integer>> infos;
    ArrayList<Integer> arr;
    HashMap<Integer, Integer> chk;
    
    public int[] solution(String s) {
        init(s);
        return proc();
    }
    
    public void init(String s){
        infos=new ArrayList<>();
        chk=new HashMap<>();
        
        StringBuilder num=new StringBuilder();
        for(int i=1;i<s.length()-1;i++){
            if(s.charAt(i)=='{'){
                arr=new ArrayList<>();
            }
            else if(s.charAt(i)==','){
                if(num.length()>0){
                    arr.add(Integer.parseInt(num.toString()));
                    num=new StringBuilder();
                }
                
            }
            else if(s.charAt(i)=='}'){
                arr.add(Integer.parseInt(num.toString()));
                num=new StringBuilder();
                infos.add(arr);
            }
            else{
                num.append(s.charAt(i));
            }
        }
        
    }
    
    public int[] proc(){
        infos.sort((a,b)->Integer.compare(a.size(),b.size()));
        int idx=0;
        
        for(ArrayList<Integer> temp: infos){
            for(int num: temp){
                //System.out.print(num+" ");
                if(!chk.containsKey(num)){
                    chk.put(num,idx++);
                }
            }
            System.out.println();
        }
        
        int[] ans=new int[chk.size()];
        
        for(Map.Entry<Integer, Integer> info: chk.entrySet()){
            ans[info.getValue()]=info.getKey();
        }
        
        return ans;
    }
}
반응형
반응형

어셈블리어

우리가 기존에 배우던 c, c++, Java 같은 언어들이 고급언어이고, 어셈블리어는 기계어(기계어는 0과 1로만 이루어진 것임)와 거의 가까운 저급언어라고 합니다. 프로그래밍 언어가 기계어에 가까울수록 어려운 대신 명령 실행 속도가 빠릅니다. python같은 언어를 문제 풀 때 실행시켜보면 메모리를 엄청 많이 잡아먹고 실행속도가 C보다 더 느리다는 것을 알 수가 있죠.

우선 linux에서 할 것이기 때문에 우분투와 가상머신을 다운로드 해주세요(과정은 생략)

그리고 terminal에 sudo apt-get install nasm을 치면 다운로드가 완료됩니다.

그럼 시작해볼게요!!

 

 

어셈블리어(Assembly Language)로 Hello World 출력하기

 

nano 파일명.s: nano는 에디터 프로그램으로 마치 메모장처럼 어떤 내용을 작성할 수 있는 프로그램을 말함. 즉 .s를 통해 에셈블리 소스코드 파일을 생성하겠다는 것을 말함.

 

 
nano프로그램을 실행시킨 모습

 

이것을 치시면 됩니다.

 

여기서 data는 프로그램에서 사용되는 문자열 같은 데이터를 저장할 수 있는 공간을 의미합니다.

text: 위에서부터 차례대로 읽어내려가는 소스코드 자체를 의미
_start: C언어에서 main 함수보다 먼저 실행되는 함수
mov: 어떠한 레지스터 안에 특정한 값을 넣는 하나의 명령어
mov rax, 1: rax라는 레지스터 안에 1을 넣겠다는 뜻

 

프로그램을 끝낼 때는 ctrl x를 누르고 y를 눌러주고 enter를 치면 나올 수 있습니다.

여기서 cat helloworld.s를 치게 되면 helloworld 파일의 내용을 볼 수 있습니다.

 

 

 

nasm -f elf64 -o helloworld.o helloworld.s: 만든 파일을 목적코드로 변환
ld -o helloworld helloworld.o: 실행할 수 있는 프로그램으로 만들어줌
ls를 쳐서 실행할 수 있는 프로그램이 생겨난 것을 볼 수 있음(linux의 경우 연두색으로 표시된 것은 실행할 수 있음을 뜻함)
./helloworld를 치시면 파일이 실행되면서 Hello World가 뜨게 됩니다.

 

만약에 세그멘테이션 오류가 뜨셨다면 section .data를 써야하는데 section.data라고 붙여쓰신 경우일겁니다.

편집
nano helloworld.s를 누르면 다시 편집할 수 있습니다. 또는
vi helloworld.s: vi 편집기 실행, 편집을 할 수 있게 됨

 

여기서 i를 누르셔야 편집을 할 수 있게 됩니다.

나갈 때: ESC를 누르면 INSERT라는 문구가 사라짐

:q : 나감
:w : 저장
:wq : 저장하고 나가기

 

vi 편집기에 대해 더 자세히 알고 싶다면

https://dog-developers.tistory.com/43

 

vim 설치 및 설정

https://norux.me/13

 

 
파일이 제거 되었음을 알 수 있음

 

rm 파일: 파일 제거(Remove)

 

 


 

레지스터의 용도와 시스템 콜 이해하기

 

 
위에서부터 64비트, 32비트, 16비트, 8비트짜리 레지스터를 보여줌

 

64비트는 레지스터 이름으로 앞에 R이 쓰인다는 것을 알 수 있고, 32비트는 E라는 것을 알 수 있네요.

 

 

 
레지스터의 크기 비교
 

 

 

RDX의 반이 EDX, 그것의 반이 DX, DL이네요.

 

//데이터 레지스터

★RAX: system call의 실질적인 번호를 가르키는 레지스터이자 함수가 실행된 다음 그 결과가 담기는 레지스터
RBX: base register로 메모리 주소를 저장할 때 쓰임
RCX: Counter register로 주로 반복문에 많이 사용됨
RDX: Data register로 RAX와 함께 많이 사용됨

 

//pointer register

RSI: 메모리를 이동하거나 비교할 때 그 출발지 주소를 가리킬 때 사용
RDI: 메모리를 이동하거나 비교할 때 그 목적지 주소를 가리킬 때 사용
RBP: 함수의 파라미터나 변수의 주소를 가리킬 때 사용
★RSP: stack의 삽입 및 삭제 명령에 의해서 변경되는 스택에서 가장 위에 있는 주소를 가리키는 하나의 레지스터
나머지 r8~r15는 함수의 매개변수로서 사용됨

 

//시스템 콜(system call)

 

 
64 bit system call table

 

table을 더보고 싶다면

https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/

 

%rax: 위에서 설명했던 레지스터죠. 어떠한 시스템 콜 함수를 불러올 때 그 번호를 가르킴.

즉, 시스템 콜 함수를 사용하기 전에 rax에 0이라는 값이 담겨 있다면 sys_read 함수를 사용한다고 해석하시면 됩니다.

예를 들어 sys_write 같은 경우에 rdi는 매개변수로서 fd(file descriptor) 역할을 한다는 것을 알 수 있고, rsi에는 어떤 문자를 출력할지, 출력할 문자열의 길이는 rdx에 담으면 됩니다.

 

 

 

그전에 썼던 걸 가져와봤는데요, 이제 해석할 수 있게 되었습니다.

rax에 1을 할당함으로써 system_write를 호출한다고 얘기를 해주고, rdi에 fd에 1을 넣음으로써 우리가 어떤 문자열을 출력하겠다고 시스템 콜 함수 매개변수로 넣어주고, rsi에 msg를 넣음으로써 msg, 즉 Hello World를 출력할 수 있게 한 후 rdx에 12을 넣어줌으로써 문자열 길이를 정해준 후 syscall을 써줘 Hello world를 출력하게 만듭니다.

밑에 rax에 60을 할당해줬는데요, 60은 sys_exit로 프로그램을 종료한다는 뜻입니다.

 

 

 

 

error_code를 써줘야 하는데 rdi에 0을 넣음으로써 안전하게 종료할 수 있습니다.

 

어셈블리 명령어

 

mov x, y
xy
and x, y
xx and y
or x, y
xx or y
xor x, y
xx xor y
add x, y
xx + y
sub x, y
xxy
inc x
xx + 1
dec x
xx – 1
syscall
Invoke an operating system routine
(운영체제에게 기능을 수행해달라고 하는 하나의 수단)
db
A pseudo-instruction that declares bytes that will be in memory when the program runs
(프로그램을 실행할 때 메모리를 선언하는 의사 명령)

 


 

메모리 구조 이해하기

 

 
메모리의 구조

 

 

 

Stack: 한 쪽 끝에서만 자료를 넣고 뺄 수 있는 LIO(Last In First Out) 형식의 자료 구조

스택은 취약점이 많이 발생하는 공간입니다.

 

 

 
stack

 

 

heap: 동적으로 할당되는 변수들이 위치하는 공간 Malloc에서 할당된 데이터들의 공간
BSS: 프로그램에서 사용된 변수(초기화가 되지 않은 변수)들이 실제적으로 위치해 있는 공간
Data: 프로그램에서 사용된 변수(초기화가 된 변수)들이 실제적으로 위치해 있는 공간
Text: 실제로 작성한 소스코드들의 공간

 

 


 

스택 프레임(Stack Frame) 이해하기

 

스택과 관련된 c파일을 만들어보겠습니다.

nano sum.c
 

이걸 쳐주세요

 

 

 

gcc: C코드를 컴파일하는 프로그램
nasm: 에셈블리어를 컴파일하는 프로그램

 

gcc 설치

https://byd0105.tistory.com/9

 

 

 
sum이라는 c언어 파일을 assembly코드로 바꿔주는 명령어
vi sum.a
 
이것을 입력해 어셈블리 파일을 열어주면
 

 

이렇게 어셈블리어 형태로 바뀐 것을 볼 수 있습니다:) esc->:q 누르셔서 나간 후 터미널에서

nano sum.c
 

를 치면 아까 작성했던 c파일이 나옵니다.

 

 
sum.c에서 main 함수의 stack 프레임

 

 

RET(return address): 특정한 함수가 끝난 후에 돌아갈 장소
RBP: 스택이 시작하는 base pointer
변수 C: int c 를 선언

 

 

 

 

 

 

위에서부터 하나씩 꺼내지면서 변수 C에 3이 담기게 되고 C가 return 값으로 가면서 main을 불러온 곳으로 돌려주게됩니다.

sum파일을 실행

sum파일에 들어가서 printf를 추가해서 c를 출력하게 만들수도 있습니다.

여기서 stack frame의 취약점이 RET를 바꾸어서 특정 함수가 돌아가는 위치를 해커가 임의로 조작해서 서버에 나쁜짓을 끼칠 수 있다는 것입니다. 대표적인 기법들로 버퍼오버플로우가 있습니다.

 

sum파일의 어셈블리어 코드(main 부분)

 

main에서 call sum 부분을 봐서 sum 함수를 불러왔다는 것을 알 수 있습니다.

pushq %rbp: rbp를 push한다
movq %rsp, %rbp : rbp에 rsp를 대입한다.
subq $16, %rsp: rsp에서 메모리16을 뺀다
movl $2, %esi : esi에 2를 대입한다
movl $1, %edi : edi에 1을 대입한다
call sum : sum 함수를 불러온다

 

음.. 근데 nasm에는 mov x,y : x←y, 즉 y를 x에 대입한다고 했는데 실제로는 반대네요...아무래도 무언가 뒤에 붙어있으면 위치를 바꿔주나봅니다...(아니면 어셈블리어로 바꿀 때 시스템이 바꿔준다던가??)

 

mov나 push뒤에 붙는 l,b,w는 오퍼랜드의 크기를 뜻합니다.

movl: 32bit 크기를 다룸
movw: 16bit 크기를 다룸
movb: 8bit 크기를 다룸

 

 

call sum 전까지

 

pushq %rbp: rbp를 push한다
movq %rsp, %rbp : rbp에 rsp를 대입한다.
movl %edi, -4(%rbp) : rbp의 -4 위치에 edi를 대입한다
movl %esi, -8(%rbp) : rbp의 -8 위치에 esi를 대입한다
addl %edx, %eax : edx와 eax의 값을 더한 후 eax에 넣어준다
popq %rbp : rbp를 꺼낸다
eax는 rax와 마찬가지로 특정한 함수가 끝날 때 그 반환값을 가지고 있는 레지스터

 

sum()

 

call sum후에

movl %eax, -4(%rbp): eax를 -4위치 rbp에 넣어준다
movl -4(%rbp), %eax: -4위치 rbp를 eax에 넣어준다
leave, ret(return)후 최종적으로 3이라는 반환값을 가지게 됨

 

 


어셈블리어(Assembly Language)로 에코 프로그램 만들기

 

에코 프로그램: 내가 입력한 문자를 그대로 출력해주는 프로그램

nano echo.s를 쳐서 파일을 만들어보겠습니다

 

똑같은 값을 xor 해주게 되면 0이라는 값이 담깁니다. mov rax, 0 과 같습니다. 즉 0으로 초기화해주겠다는 것이죠

 
 
AND
OR
XOR
0 0
0
0
0
0 1
0
1
1
1 0
0
1
1
1 1
1
1
0

 

mov rbx, rax~ mov rdx, rax까지는 0으로 초기화 해준다는 뜻입니다.

sub rsp, 64: rbx=rsp이기 때문에 rsp에 6를 빼줘 데이터를 담을 수 있게 합니다.

rax값에 따라 syscall이 바뀐다고 했었습니다.

fd=0 : 무언가를 읽음
fd=1 : 무언가를 씀

 

mov rsi, rsp : rsi에 rsp의 주소값이 들어간다

mov rdx, 63 : 63만큼 문자열을 불러온다.

즉 사용자가 문자를 입력하고 그 문자를 읽고 rax에 저장합니다.

그다음 rax에 1을 대입하고, rdi에 1을 대입합니다.

sys_write를 불러오면서 그 문자를 출력해주게 됩니다.

rax에 60을 대입해 끝내줍니다.

echo 파일을 목적프로그램으로 변환해 프로그램을 실행합니다.

 

 


 

어셈블리어(Assembly Language) 기본 문법

- LEA: A의 값을 B의 값으로 연산을 포함하여 복사함. LEA EAX, [EAX+1000]은 EAX에 1000을 넣은 값을 다시 EAX에 삽입함, 이처럼 연산을 포함할 수 있음
- JMP: 특정한 위치로 건너 뛰어 코드 실행, JMP A라고 하면 A의 위치로 뛰어서 코드가 실행됨, 비슷하게 조건 점프 명령도 존재. JA, JB, JE 등의 명령어는 두 인자를 받아서 비교한 뒤에 결과에 따라서 다른 방향으로 점프할 수 있음.
- CALL: 함수를 호출했다가 다시 원래 위치로 돌아올 때 사용. JMP와 다른 점은 실행한 뒤에 끝나게 되면 RET에 저장하고 다시 원래 상태로 돌아온다는 점이 있음.
- NOP: 아무 작업도 하지 않는 명령어. 1Byte의 공간을 차지
- RET: 현재 함수가 끝난 뒤에 돌아갈 주소를 지정하기 위해 사용
- PUSH: 스택에 해당 값을 넣음
- POP: 스택에 있는 값을 뺴냄
- LEAVE: 현재까지의 메모리 스택을 비우고 EBP를 자신을 호출한 메모리 주소로 채움. 실행 중인 함수를 종료하기 위해 정리하는 작업에 사용됨.

 


어셈블리어(Assembly Language)로 반복문 구현하기

 

nano loop.s
 

loop 파일을 만들어볼게요

mov rax 60, syscall 하지 않으면 세그멘테이션 오류가 뜹니다.(참고하세요)

종료까지 적어줍니다.

해주면 A가 출력됩니다.

이제 A가 여러 번 출력되도록 만들어 볼게요~~

 

cmp: 어떠한 것을 비교하는 compare 함수임

cmp r10, 100: r10과 100을 비교하여

je: jump equal, 비교 결과가 같을 때 점프
je done: r10이 100이면 done으로 간다
syscall: 100이 아니면 syscall 한다
mov rax, 1: rax는 함수를 실행하면 어떤 값이 담기기 때문에 1로 다시 초기화합니다
inc r10: r10을 1증가시킨다
jmp again: again으로 다시 돌아간다
done: 함수를 끝낸다

 

 

더 많은 명령어를 알고 싶다면

http://pyrasis.com/blog/entry/ReverseEngineeringForNewbieAssemblyOperation

 

 

출처:

https://youtu.be/uOIq-P2eQXs

:동빈나의 시스템 해킹 강좌(15강까지 있습니다.)

 

참고:

https://cs.lmu.edu/~ray/notes/nasmtutorial/

 

 

반응형

'Hacking > Assembly' 카테고리의 다른 글

어셈블리어(Assembly Language) 기초 정리  (0) 2026.02.15
반응형

우리가 기존에 배우던 C, C++, Java 같은 언어들은 고급 언어이고,
어셈블리어는 기계어(0과 1로만 이루어진 언어)에 매우 가까운 저급 언어입니다.

프로그래밍 언어는 기계어에 가까울수록 작성과 이해는 어렵지만 실행 속도는 빠릅니다.
예를 들어 Python으로 문제를 실행해보면 메모리를 많이 사용하고, 실행 속도도 C보다 느린 것을 확인할 수 있습니다.


개발 환경 준비 (Linux 기준)

Linux 환경에서 진행할 것이므로, 우분투와 가상머신을 설치합니다.
(설치 과정은 생략)

NASM 설치

sudo apt-get install nasm

어셈블리어로 Hello World 출력하기

파일 생성

nano helloworld.s

nano는 메모장처럼 텍스트를 작성할 수 있는 에디터입니다.
.s 확장자는 어셈블리 소스 파일을 의미합니다.


코드 구조 설명

  • section .data
    프로그램에서 사용하는 문자열 같은 데이터를 저장하는 공간
  • section .text
    실제 실행되는 코드 영역
  • _start
    C 언어의 main 함수보다 먼저 실행되는 시작 지점

주요 명령어 설명

  • mov
    레지스터에 값을 대입하는 명령어
    • mov rax, 1 → rax 레지스터에 1을 저장

파일 저장 및 종료

  • Ctrl + X → Y → Enter

파일 내용 확인

cat helloworld.s

컴파일 및 실행

nasm -f elf64 -o helloworld.o helloworld.s
ld -o helloworld helloworld.o
ls
./helloworld
  • Linux에서는 실행 가능한 파일이 연두색으로 표시됩니다.

세그멘테이션 오류가 날 경우

section.data

처럼 붙여 썼을 가능성이 큽니다.
반드시 아래처럼 작성해야 합니다.

section .data

vi / vim 편집기 사용법

파일 열기

vi helloworld.s
  • i : 입력 모드
  • ESC : 명령 모드
  • :q : 종료
  • :w : 저장
  • :wq : 저장 후 종료

vim 설치:

sudo apt-get install vim

레지스터와 시스템 콜 이해하기

레지스터 크기

  • 64bit : RAX, RBX, RCX …
  • 32bit : EAX, EBX …
  • 16bit : AX, BX …
  • 8bit : AL, BL …

예:

  • RDX → EDX → DX → DL

주요 레지스터 용도

데이터 레지스터

  • RAX
    시스템 콜 번호 / 함수 반환값
  • RBX
    메모리 주소 저장
  • RCX
    반복문에서 카운터 역할
  • RDX
    데이터 처리용

포인터 레지스터

  • RSI
    출발지 주소
  • RDI
    목적지 주소
  • RBP
    스택 기준 주소
  • RSP
    현재 스택 최상단 주소
  • r8 ~ r15 : 함수 인자 전달용

시스템 콜(System Call)

64bit Linux에서는 syscall 명령어를 사용합니다.

  • rax : 시스템 콜 번호
  • rdi, rsi, rdx : 매개변수

예시:

  • sys_write
    • rax = 1
    • rdi = 1 (stdout)
    • rsi = 문자열 주소
    • rdx = 문자열 길이
  • sys_exit
    • rax = 60
    • rdi = 종료 코드

어셈블리 주요 명령어 정리

명령어설명

mov x, y x ← y
and x, y x ← x and y
or x, y x ← x or y
xor x, y x ← x xor y
add x, y x ← x + y
sub x, y x ← x - y
inc x x ← x + 1
dec x x ← x - 1
syscall 시스템 콜 호출
db 메모리 데이터 선언

메모리 구조 이해하기

  • Stack
    LIFO 구조, 취약점이 많이 발생
  • Heap
    동적 메모리 영역 (malloc)
  • BSS
    초기화되지 않은 전역 변수
  • Data
    초기화된 전역 변수
  • Text
    실행 코드 영역

스택 프레임(Stack Frame)

C 코드 작성

nano sum.c

어셈블리 코드로 변환

gcc -S sum.c
vi sum.s

함수 호출 과정

  • push rbp
  • mov rsp, rbp
  • sub rsp, 16
  • 인자 전달
  • call sum
  • leave
  • ret

오퍼랜드 크기 접미사

  • movl : 32bit
  • movw : 16bit
  • movb : 8bit

에코(Echo) 프로그램 만들기

입력한 문자열을 그대로 출력하는 프로그램

nano echo.s
  • xor rax, rax : rax를 0으로 초기화
  • sub rsp, 64 : 입력 버퍼 공간 확보
  • sys_read → 입력 받기
  • sys_write → 출력
  • sys_exit → 종료

반복문 구현하기

nano loop.s

주요 흐름

  • cmp : 비교
  • je : 같으면 점프
  • jmp : 무조건 점프
  • inc : 증가
  • syscall : 출력
반응형

'Hacking > Assembly' 카테고리의 다른 글

Nasm을 이용한 Assembly 배우기-0  (0) 2026.02.15
반응형

2019 KAKAO BLIND RECRUITMENT 후보키 문제를 풀어보겠다.

1. 문제

이런 테이블(2차원 배열)이 주어질 때, 후보키가 될 수 있는 개수를 구하는 문제다.

2. 링크

프로그래머스 2019 KAKAO BLIND - 후보키 문제 링크

3. 풀이

문제에서 유일성, 최소성 2가지 조건을 만족해야 한다.

최소 뽑을 수 있는 것부터 유일성을 검사한 후, 유일성 통과가 안될 시에 뽑는 개수를 한 개씩 늘려가면서 유일성을 만족하는 걸 찾는다.

  1. 유일성 만족 확인
    • 각 컬럼의 문자를 공백을 사이에 두고 하나의 문자열로 통합 (공백을 둔 이유는 혹시나 서로 다른 컬럼인데 이어졌을 때, 같아질 때를 방지하기 위한 것, ex) abs, sbs / ab, ssbs => abssbs 로 같아지게 된다.
    • 이 문자들의 유일성 검사를 hashSet을 이용함.
    • 행에 속하는 문자들 통합이 hashSet에 있을 경우, 유일성을 만족 못함, 만족할 경우 hashSet에 넣음
  2. 최소성 만족 확인(정답 코드의 경우)
    • bit 마스킹을 이용해 만족하는지 확인
    • (뽑은 컬럼 값의 bit 마스크 & 정답 후보에 있는 bit 마스크) = 정답 후보에 있는 bit 마스크 일 경우, 최소성 만족을 못함

여기서 (3, 2) 이런 식으로 (2, 3)의 순서만 바뀐 조합은 안 나오게 한다.

1) 오답

처음 코드에서는 42.9점으로 오답이 나왔었다. 이유는 다음과 같은 반례 때문이다.

반례
[["1", "2", "3"], ["2", "3", "1"], ["2", "3", "3"]]
정답: 2 => (0,2), (1,2)
return 3 => (0,1,2), (0,2), (1,2)

최소성을 보장 못한다.
이 코드의 경우 dfs 방식으로 뽑은 개수별로 순차적으로 확인하지를 않는다.
예를 들어, 컬럼 (1,3)의 조합이 유일성을 만족한다고 했을 때, 탐색을 다음과 같이 하게 된다.

(1) → (1,2) → (1,2,3) ⇒ 유일성 만족, 정답 개수++

    → (1,3) → 유일성 만족, 정답 개수++

이때 (1,2,3)은 (1,3)이 이미 후보키이기 때문에 최소성을 만족하지 못한다.
⇒ 개수를 순차적으로 뽑는 bfs 방법을 사용해야 한다.

  • 코드
import java.util.*;
class Solution {

    int ans=0, row, col;
    String[][] rel;

    public int solution(String[][] relation) {
        rel=relation;
        row=relation.length;
        col=relation[0].length;

        proc(0,new ArrayList<>());

        return ans;
    }

    //유일성을 못 맞출 경우, 컬럼 조합을 늘려간다.
    public void proc(int cnt, ArrayList<Integer> combi){
        // if(cnt>=col) return;

        int start=combi.isEmpty()?0:combi.get(combi.size()-1)+1;

        for(int j=start;j<col;j++){
            boolean chk=true;
            HashSet<String> hs=new HashSet<>();

            for(int i=0;i<row;i++){
                StringBuilder sb=new StringBuilder();
                for(int k=0;k<cnt;k++){
                    sb.append(rel[i][combi.get(k)]+" ");
                }

                sb.append(rel[i][j]);

                String result=new String(sb);

                if(hs.contains(result)){
                    chk=false;

                    ArrayList<Integer> temp=new ArrayList(combi);
                    temp.add(j);
                    proc(cnt+1, temp);

                    break;
                }

                hs.add(result);
            }

            if(chk){
                ans++;
            }

        }  
    }


}

2) 정답

bfs 방식으로 바꾸고, 비트마스킹 사용
유일성을 만족했을 시, 비트마스킹을 통해 부분 집합이 이미 유일성을 만족하지 않는지 확인한다.

예를 들어, 아까와 같은 예시로 컬럼 (1,3)의 조합이 유일성을 만족한다고 했을 때를 생각해본다.
지금 같은 bfs 방식일 경우, 다음과 같이 검사를 한다.

⭕: 유일성 만족, ❌: 유일성 불만족
1 ❌→ 2 ❌ → 3 ❌ → (1, 2) ❌ → (1, 3) ⭕ → (1, 4) ❌→ (2, 3) ❌ → (1, 2, 3) ⭕

유일성을 만족하는 조합은 (1, 3), (1, 2, 3), 이렇게 2가지다.

여기서 (1, 2, 3)은 이미 (1, 3)이 후보키이기 때문에 최소성이 만족하지 못한다. 따라서 부분 집합이 이미 후보키일 경우, 걸러줘야 한다.

비트마스킹으로 보면,

(1, 2, 3) ⇒ 0111
(1, 3) ⇒ 0101
& ⇒ 0101 == 0101

따라서 & 연산을 했을 때, 후보키랑 같은 게 나오면 최소성을 불만족하게 된다.

만약, (1, 4), (1, 2, 3) 이 후보키인게 있다고 하자. 그러면

(1, 2, 3) ⇒ 0111
(1, 4) ⇒ 1001
& ⇒ 0001 ≠ 1001

(1, 4)는 (1, 2, 3)의 부분 집합이 아닌걸로 정확하게 나온다.

  • 코드
class Solution {
    int row, col;
    String[][] rel;

    public int solution(String[][] relation) {
        rel=relation;
        row=relation.length;
        col=relation[0].length;

        int ans=proc();

        return ans;
    }

    //유일성을 못 맞출 경우, 컬럼 조합을 늘려간다.
    public int proc(){
        ArrayDeque<int[]> q=new ArrayDeque<>(); // 비트마스킹, 맨 뒤 idx
        q.add(new int[]{0,-1});
        ArrayList<Integer> ans=new ArrayList<>();

        while(!q.isEmpty()){
            int[] info=q.poll();
            int start=info[1]+1;

            for(int j=start;j<col;j++){
                boolean chk=true;
                HashSet<String> hs=new HashSet<>();
                int bit=info[0]|1<<j;

                for(int i=0;i<row;i++){

                    StringBuilder sb=new StringBuilder();

                    for(int k=0;k<8;k++){
                        if((info[0]&1<<k)!=0){
                            sb.append(rel[i][k]+" ");
                        }
                    }

                    sb.append(rel[i][j]);
                    String result=new String(sb);

                    if(hs.contains(result)){
                        chk=false;

                        q.add(new int[]{bit, j});

                        break;
                    }

                    hs.add(result);
                }

                if(chk){
                    boolean isHubo=true;

                    for(int hubo : ans){
                        if((hubo&bit)==hubo){
                            isHubo=false;
                            break;
                        }
                    }

                    if(isHubo) {
                        ans.add(bit);
                    }
                }

            }  
        }

        return ans.size();

    }

}
  • 실행 시간
테스트 1 〉	통과 (2.70ms, 87.5MB)
테스트 2 〉	통과 (2.44ms, 86.2MB)
테스트 3 〉	통과 (2.19ms, 85.8MB)
테스트 4 〉	통과 (2.88ms, 91.1MB)
테스트 5 〉	통과 (2.62ms, 75.3MB)
테스트 6 〉	통과 (0.44ms, 82MB)
테스트 7 〉	통과 (0.40ms, 67.9MB)
테스트 8 〉	통과 (2.71ms, 75.9MB)
테스트 9 〉	통과 (4.11ms, 84.7MB)
테스트 10 〉	통과 (0.59ms, 87.5MB)
테스트 11 〉	통과 (3.46ms, 86.6MB)
테스트 12 〉	통과 (3.63ms, 75.8MB)
테스트 13 〉	통과 (3.78ms, 72.3MB)
테스트 14 〉	통과 (4.25ms, 83.8MB)
테스트 15 〉	통과 (2.14ms, 87.4MB)
테스트 16 〉	통과 (2.51ms, 74.8MB)
테스트 17 〉	통과 (3.15ms, 75.8MB)
테스트 18 〉	통과 (4.32ms, 77.7MB)
테스트 19 〉	통과 (3.38ms, 90.8MB)
테스트 20 〉	통과 (4.50ms, 75.6MB)
테스트 21 〉	통과 (4.58ms, 90.5MB)
테스트 22 〉	통과 (4.84ms, 93.6MB)
테스트 23 〉	통과 (2.25ms, 84.1MB)
테스트 24 〉	통과 (3.79ms, 85MB)
테스트 25 〉	통과 (4.65ms, 73.1MB)
테스트 26 〉	통과 (4.68ms, 87.5MB)
테스트 27 〉	통과 (2.99ms, 90.9MB)
테스트 28 〉	통과 (4.26ms, 84.9MB)

4. 시간 개선(문자열 체이닝)

StringBuilder 같은 클래스에서 append() 메서드를 연달아 이어서 호출하는 방식

1) 기존 코드 (임시 문자열 생성)

sb.append(rel[i][k] + " ");

rel[i][k] + " " 때문에, rel[i][k]와 " "을 합친 새로운 String 객체가 매번 만들어지고, 그다음에야 append()가 호출된다.
즉, 매번 불필요한 중간 문자열 객체가 생겨 성능 저하로 이어진다.

2) 문자열 체이닝 방식

sb.append(rel[i][k]).append(' ');

여기서는 먼저 rel[i][k]를 붙이고, 곧바로 ' '(공백 문자)를 붙인다.
그러면, 중간에 임시 String 객체가 전혀 안 생기고, StringBuilder 내부 버퍼에 바로 기록된다.

import java.util.*;
class Solution {
    int row, col;
    String[][] rel;

    public int solution(String[][] relation) {
        rel=relation;
        row=relation.length;
        col=relation[0].length;

        int ans=proc();

        return ans;
    }

    //유일성을 못 맞출 경우, 컬럼 조합을 늘려간다.
    public int proc(){
        ArrayDeque<int[]> q=new ArrayDeque<>(); // 비트마스킹, 맨 뒤 idx
        q.add(new int[]{0,-1});
        ArrayList<Integer> ans=new ArrayList<>();

        while(!q.isEmpty()){
            int[] info=q.poll();
            int start=info[1]+1;

            for(int j=start;j<col;j++){
                boolean chk=true;
                HashSet<String> hs=new HashSet<>();
                int bit=info[0]|1<<j;

                for(int i=0;i<row;i++){

                    StringBuilder sb=new StringBuilder();

                    for(int k=0;k<8;k++){
                        if((info[0]&1<<k)!=0){
                            sb.append(rel[i][k]).append(" "); // 체이닝 사용
                        }
                    }

                    sb.append(rel[i][j]);
                    String result=new String(sb);

                    if(hs.contains(result)){
                        chk=false;

                        q.add(new int[]{bit, j});

                        break;
                    }

                    hs.add(result);
                }

                if(chk){
                    boolean isHubo=true;

                    for(int hubo : ans){
                        if((hubo&bit)==hubo){
                            isHubo=false;
                            break;
                        }
                    }

                    if(isHubo) {
                        ans.add(bit);
                    }
                }

            }  
        }

        return ans.size();

    }

}
  • 실행 시간
테스트 1 〉	통과 (0.13ms, 75.3MB)
테스트 2 〉	통과 (0.14ms, 85MB)
테스트 3 〉	통과 (0.15ms, 72.9MB)
테스트 4 〉	통과 (0.16ms, 84.7MB)
테스트 5 〉	통과 (0.16ms, 73.9MB)
테스트 6 〉	통과 (0.10ms, 74.5MB)
테스트 7 〉	통과 (0.09ms, 80.8MB)
테스트 8 〉	통과 (0.10ms, 89.7MB)
테스트 9 〉	통과 (0.17ms, 79.6MB)
테스트 10 〉	통과 (0.15ms, 88.9MB)
테스트 11 〉	통과 (0.29ms, 78MB)
테스트 12 〉	통과 (0.75ms, 79.6MB)
테스트 13 〉	통과 (0.46ms, 85.9MB)
테스트 14 〉	통과 (0.15ms, 90MB)
테스트 15 〉	통과 (0.10ms, 84.8MB)
테스트 16 〉	통과 (0.17ms, 76.4MB)
테스트 17 〉	통과 (0.18ms, 76.5MB)
테스트 18 〉	통과 (1.51ms, 87.9MB)
테스트 19 〉	통과 (1.37ms, 74.8MB)
테스트 20 〉	통과 (1.35ms, 70.5MB)
테스트 21 〉	통과 (2.55ms, 85.3MB)
테스트 22 〉	통과 (1.64ms, 85.7MB)
테스트 23 〉	통과 (0.15ms, 82MB)
테스트 24 〉	통과 (0.61ms, 91.7MB)
테스트 25 〉	통과 (1.98ms, 80.9MB)
테스트 26 〉	통과 (1.53ms, 83.2MB)
테스트 27 〉	통과 (0.80ms, 90.2MB)
테스트 28 〉	통과 (0.71ms, 78.5MB)

 

 

5. 참고

비트마스킹을 안쓰고 했을 때 코드도 남겨놓겠다.
비트마스킹 대신 *10, +를 사용했다.
예를 들어, 뽑는 컬럼이 1, 2, 3이면 123이 된다.

  • 코드
import java.util.*;

class Solution {  
int row, col;  
String[][] rel;

public int solution(String[][] relation) {
    rel=relation;
    row=relation.length;
    col=relation[0].length;

    int ans=proc();

    return ans;
}

//유일성을 못 맞출 경우, 컬럼 조합을 늘려간다.
public int proc(){
    ArrayDeque<int[]> q=new ArrayDeque<>(); // 뽑은 조합, 맨 뒤 idx
    q.add(new int[]{0,-1});
    ArrayList<Integer> ans=new ArrayList<>();

    while(!q.isEmpty()){
        int[] info=q.poll();
        int start=info[1]+1;

        for(int j=start;j<col;j++){
            boolean chk=true;
            HashSet<String> hs=new HashSet<>();
            int bit=info[0]*10+(j+1);

            for(int i=0;i<row;i++){

                StringBuilder sb=new StringBuilder();
                int num=info[0];

                while(num>0){
                    int idx=num%10;
                    num/=10;
                    sb.append(rel[i][idx-1]+" ");
                }

                sb.append(rel[i][j]);
                String result=new String(sb);

                if(hs.contains(result)){
                    chk=false;

                    q.add(new int[]{bit, j});

                    break;
                }

                hs.add(result);
            }

            if(chk){
                boolean isHubo=true;

                for(int hubo : ans){
                    int num=hubo;
                    boolean isSub=true;

                    // 부분 집합이 이미 있는지 확인
                    while(num>0){
                        int ele=num%10;
                        num/=10;
                        boolean isExist=false;

                        int num2=bit;
                        while(num2>0){
                            int ele2=num2%10;
                            num2/=10;

                            if(ele==ele2){
                                isExist=true;
                                break;
                            }
                        }

                        if(!isExist){
                            isSub=false;
                            break;
                        }
                    }


                    if(isSub){
                        isHubo=false;
                        break;
                    }
                }

                if(isHubo) {
                    ans.add(bit);
                }
            }

        }  
    }

    return ans.size();

  }

}
  • 실행 시간
    비트마스킹 썼을 때와 차이가 나지 않는다.
테스트 1 〉 통과 (1.99ms, 91.7MB)
테스트 2 〉 통과 (1.96ms, 72.7MB)
테스트 3 〉 통과 (2.10ms, 79.4MB)
테스트 4 〉 통과 (1.80ms, 93.7MB)
테스트 5 〉 통과 (2.08ms, 84.5MB)
테스트 6 〉 통과 (0.11ms, 82.4MB)
테스트 7 〉 통과 (0.09ms, 69.4MB)
테스트 8 〉 통과 (1.98ms, 76.1MB)
테스트 9 〉 통과 (2.25ms, 77.7MB)
테스트 10 〉 통과 (0.13ms, 82.8MB)
테스트 11 〉 통과 (2.23ms, 86.4MB)
테스트 12 〉 통과 (4.12ms, 87MB)
테스트 13 〉 통과 (2.70ms, 97.4MB)
테스트 14 〉 통과 (1.84ms, 77.1MB)
테스트 15 〉 통과 (1.79ms, 85.3MB)
테스트 16 〉 통과 (2.98ms, 84.3MB)
테스트 17 〉 통과 (2.07ms, 85.4MB)
테스트 18 〉 통과 (3.43ms, 89MB)
테스트 19 〉 통과 (3.08ms, 75.3MB)
테스트 20 〉 통과 (3.53ms, 82.9MB)
테스트 21 〉 통과 (4.11ms, 87.8MB)
테스트 22 〉 통과 (4.46ms, 92MB)
테스트 23 〉 통과 (1.93ms, 83.6MB)
테스트 24 〉 통과 (4.33ms, 83.5MB)
테스트 25 〉 통과 (5.04ms, 79.7MB)
테스트 26 〉 통과 (3.50ms, 86.9MB)
테스트 27 〉 통과 (2.63ms, 72.9MB)
테스트 28 〉 통과 (3.20ms, 85.6MB)

 

반응형
반응형

문자 선택자

특정 문자 또는 문자열을 선택하여 CSS 속성을 설정할 수 있다.

first-letter, first-line 을 사용

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      #wrap {
        width: 800px;
        margin: 0 auto;
      }
      #header {
        border-bottom: 1px solid #cccc;
      }
      #p1::first-letter,
      #p2::first-letter {
        font-size: 2em;
      }
      #p1::first-line,
      #p2::first-line {
        color: tomato;
      }
      #content > p {
        float: right;
      }
    </style>
  </head>
  <body>
    <div id="wrap">
      <div id="header">
        <h1>AYA</h1>
      </div>
      <div id="content">
        <p>-마마무</p>
        <p id="p1">
          I love you<br />
          세상을 다 줄 것처럼 말하고 Hate you 이젠 서로 화살을 겨눠 뻔하디뻔한
          bad ending 님 얼굴에 침을 뱉어 오점 하나 생겨 우린 남이 됐다 못된
          사랑놀이에 미쳐 이기적인 넌 이젠 지쳐 눈물인지 또 빗물인지 oh 넌 내게
          모욕감을 줬어
        </p>
        <p id="p2">
          눈물이 <br />
          뚝 떨어진다 no, no, no, eh, oh oh eh, dong do-do-do-dong dong 툭
          떨어진다 눈물이야 빗물이야 아야 눈물이야 빗물이야 아야 눈물이 툭
        </p>
      </div>
    </div>
  </body>
</html>
#content p:first-child::selection{
	background-color:blue;
    color:yellow;
}

selection을 이용해 마우스 커서를 끌어당길 때를 설정할 수 있다

first-child을 이용해 첫번째 태그만을 선택한다.

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      #wrap {
        width: 800px;
        margin: 0 auto;
      }
      #header {
        border-bottom: 1px solid #cccc;
      }
      #content p:first-child::selection {
        background-color: blue;
        color: red;
      }
      #p1::first-letter,
      #p2::first-letter {
        font-size: 2em;
      }
      #p1::first-line,
      #p2::first-line {
        color: tomato;
      }
      #content > p {
        float: right;
      }
    </style>
  </head>
  <body>
    <div id="wrap">
      <div id="header">
        <h1>AYA</h1>
      </div>
      <div id="content">
        <p>-마마무</p>
        <p id="p1">
          I love you<br />
          세상을 다 줄 것처럼 말하고 Hate you 이젠 서로 화살을 겨눠 뻔하디뻔한
          bad ending 님 얼굴에 침을 뱉어 오점 하나 생겨 우린 남이 됐다 못된
          사랑놀이에 미쳐 이기적인 넌 이젠 지쳐 눈물인지 또 빗물인지 oh 넌 내게
          모욕감을 줬어
        </p>
        <p id="p2">
          눈물이 <br />
          뚝 떨어진다 no, no, no, eh, oh oh eh, dong do-do-do-dong dong 툭
          떨어진다 눈물이야 빗물이야 아야 눈물이야 빗물이야 아야 눈물이 툭
        </p>
      </div>
    </div>
  </body>
</html>

 

 

링크 선택자

문서에서 링크(href)되어 있는 문자를 선택하여, CSS속성을 설정할 수 있다.

#content a::after{
	content: '-' attr(href);
}

'-'뒤에 href속성값을 붙인다

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      #wrap {
        width: 800px;
        margin: 0 auto;
      }
      #header {
        border-bottom: 1px solid #cccc;
      }
      #content a {
        text-decoration: green wavy underline;
        color: rgb(9, 45, 248);
      }
      #content a::after {
        content: "-" attr(href);
      }
    </style>
  </head>
  <body>
    <div id="wrap">
      <div id="header">
        <h1>Website</h1>
      </div>
      <div id="content">
        <ul>
          <li><a href="https://www.google.com/"> Google</a></li>
          <li><a href="https://www.naver.com/"> Naver</a></li>
        </ul>
      </div>
      <div id="footer"></div>
    </div>
  </body>
</html>

 

text-decoration => 링크 걸렸을 때 표시 설정 변경

자세한 설명↓

developer.mozilla.org/ko/docs/Web/CSS/text-decoration

 

text-decoration - CSS: Cascading Style Sheets | MDN

text-decoration CSS 단축 속성은 글씨의 장식(선) 색을 지정합니다. text-decoration-line, text-decoration-color, text-decoration-style, text-decoration-thickness속성 값을 설정합니다. The source for this interactive example is store

developer.mozilla.org

 

 

 

부정 선택자

 

#content li:not(.fa){
	background-color:#;
}

fa 클래스를 제외한 나머지

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      #wrap {
        width: 800px;
        margin: 0 auto;
      }
      #header {
        border-bottom: 1px solid #cccc;
      }
      #content a {
        text-decoration: none;
        color: rgb(0, 0, 0);
      }
      #content li:not(.no) {
        text-decoration: rgb(0, 255, 64) wavy underline;
        background-color: rgb(190, 255, 196);
      }
      #content a::after {
        content: "-" attr(href);
      }
    </style>
  </head>
  <body>
    <div id="wrap">
      <div id="header">
        <h1>Website</h1>
      </div>
      <div id="content">
        <ul>
          <li><a href="https://www.google.com/"> Google</a></li>
          <li class="no"><a href="https://www.naver.com/"> Naver</a></li>
          <li><a href="https://www.gogle.com/"> Gogle</a></li>
          <li class="no"><a href="https://www.never.com/"> Never</a></li>
        </ul>
      </div>
    </div>
  </body>
</html>

 

반응형

'Web > css' 카테고리의 다른 글

CSS-(3)  (0) 2021.02.19
CSS-(2)  (0) 2021.02.18
CSS-(1)  (2) 2021.02.05
반응형

반응 선택자

마우스의 반응에 따른 속성을 설정할 수 있다

hover: 마우스가 올라갈 때 반응함

 

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      ul > li {
        font-size: 20px;
        font-weight: bold;
        color: orange;
      }
      li:hover {
        color: blue;
      }
    </style>
  </head>
  <body>
    <ul>
      <li>menu1</li>
      <li>menu2</li>
      <li>menu3</li>
      <li>menu4</li>
      <li>menu5</li>
    </ul>
  </body>
</html>

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      ul > li {
        font-size: 20px;
        font-weight: bold;
        color: orange;
      }
      li:hover {
        color: blue;
      }
      div {
        width: 500px;
        background-color: palegoldenrod;
        margin: 100px 0 0 50px;
      }
    </style>
  </head>
  <body>
    <ul>
      <li>menu1</li>
      <li>menu2</li>
      <li>menu3</li>
      <li>menu4</li>
      <li>menu5</li>
    </ul>
    <div>
      <ol>
        <li>menu1</li>
        <li>menu2</li>
        <li>menu3</li>
        <li>menu4</li>
        <li>menu5</li>
      </ol>
    </div>
  </body>
</html>

margin: 상하좌우 여백

e.g: margin 30px =>상하좌우 30px씩 준다

margin100px 0 0 50px=>위에서 100px, 왼쪽으로 50px

margin: 0 auto => 위아래 0 왼쪽오른쪽 auto 균등 분배

margin: 0 auto의 예

상태 선택자

상태에 따라서 CSS속성이 변하는 설정을 할 수 있다.

enable, disable, focus 등 상태에 따라 속성을 줄 수 있다.

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      input:focus {
        border: 20px solid rebeccapurple;
        padding: 20px;
      }
      input:enabled {
        color: salmon;
        font-weight: bold;
      }
      input:disabled {
        color: rgb(252, 214, 0);
      }
    </style>
  </head>
  <body>
    <div>
      <form>
        이름: <input type="text" name="uname" /><br />
        아이디: <input type="text" name="uid" /><br />
        비밀번호:
        <input
          type="password"
          name="upw"
          value="12345"
          disabled="disabled"
        /><br />
      </form>
    </div>
  </body>
</html>

 

html부분

disable =>상태변경 불가

css부분

enable=>변경 가능할 경우 속성

disalbe=>변경 불가능할 경우 속성

focus=>마우스 클릭(focus)일 경우 속성(양식의 입력칸일 때)

구조 선택자

구조에 따라서 CSS속성이 변하는 설정을 할 수 있다

맨 위, 맨 아래는 어떻게 해라, 짝수 구조는 어떻게 해라 등등을 할 때 쓰임

 

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      #content {
        width: 300px;
      }
      ul li {
        list-style: none;
        border: 1px solid;
        padding: 10px;
        background-color: #fffdfd;
        font-weight: bold;
        font-size: 20px;
      }
      ul li a {
        color: #000000;
      }
      ul li:nth-child(2n + 1) {
        background-color: #f8a7a7;
      }
      ul li:first-child,
      ul li:last-child {
        background-color: yellow;
      }
      ul li:first-child {
        border-radius: 10px 10px 0 0;
      }
      ul li:last-child {
        border-radius: 0 0 10px 10px;
      }
    </style>
  </head>
  <body>
    <div id="content">
      <ul>
        <li><a href="#">menu1</a></li>
        <li><a href="#">menu2</a></li>
        <li><a href="#">menu3</a></li>
        <li><a href="#">menu4</a></li>
        <li><a href="#">menu5</a></li>
        <li><a href="#">menu6</a></li>
        <li><a href="#">menu7</a></li>
        <li><a href="#">menu8</a></li>
      </ul>
    </div>
  </body>
</html>

list style=>앞에 글머리표 지정, none일 경우 빠짐

자세한 내용: ↓

webberstudy.com/html-css/css-1/list-style/

 

list-style (리스트 스타일)

HTML 태그 중 ol, ul, li 요소에 스타일을 줄 수 있는 CSS 속성인 list-style 속성을 살펴 봅니다.

webberstudy.com

nth-child(2n+1)=> 2n+1번째 태그 선택, 즉 홀수번째

first-child=>맨 위

last-child=>맨 아래

border-radius=>바깥쪽 둥글게 (좌상단 우상단 우하단 좌하단)

 

전체적인 레이아웃 설정

 

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      #header,
      #content,
      #footer {
        width: 2000px;
        margin: 0 auto;
        overflow: scroll;
      }
      #header .left_space,
      #content .left_space,
      #footer .left_space {
        width: 150px;
        height: 150px;
        float: left;
        background-color: #f3f3f3;
        border: 1px solid #cccccc;
      }
      #header .center_space,
      #content .center_space,
      #footer .center_space {
        width: 700px;
        height: 150px;
        float: left;
        background-color: #f3f3f3;
        border: 1px solid #cccccc;
      }
      #header .right_space,
      #content .right_space,
      #footer .right_space {
        width: 150px;
        height: 150px;
        float: left;
        background-color: #f3f3f3;
        border: 1px solid #cccccc;
      }
      #header .left_space,
      #footer .right_space {
        border-radius: 20px 0 20px 0;
      }
      #header .right_space,
      #footer .left_space {
        border-radius: 0px 20px 0px 20px;
      }
      #header .center_space {
        border-radius: 0 0 20px 20px;
      }
      #header .right_space {
        border-radius: 0 20px 0 20px;
      }
      #content .left_space {
        border-radius: 0 20px 20px 0;
        height: 300px;
      }
      #content .center_space {
        border-radius: 20px 20px 20px 20px;
        height: 300px;
      }
      #content .right_space {
        border-radius: 20px 0 0 20px;
        height: 300px;
      }
      #footer .center_space {
        border-radius: 20px 20px 0 0;
      }
      #content .center_space ul li {
        list-style: none;
        float: left;
        padding: 0 40px;
        font-weight: bold;
        font-size: 20px;
      }
      #content .hehe {
        clear: both;
        padding: 10px;
      }
    </style>
  </head>
  <body>
    <div id="header">
      <div class="left_space"></div>
      <div class="center_space"></div>
      <div class="right_space"></div>
    </div>
    <div id="content">
      <div class="left_space"></div>
      <div class="center_space">
        <div>
          <ul>
            <li>menu1</li>
            <li>menu2</li>
            <li>menu3</li>
            <li>menu4</li>
          </ul>
        </div>
        <div class="hehe">
          <h1>헤헤헤</h1>
          <p>가나다라마바사아자차카타파하</p>
        </div>
      </div>
      <div class="right_space"></div>
    </div>
    <div id="footer">
      <div class="left_space"></div>
      <div class="center_space"></div>
      <div class="right_space"></div>
    </div>
  </body>
</html>

 

차근차근보면 별로 어렵지 않습니다

반응형

'Web > css' 카테고리의 다른 글

CSS-(4)  (0) 2021.02.19
CSS-(2)  (0) 2021.02.18
CSS-(1)  (2) 2021.02.05
반응형

id(#)와 class(.)

태그의 id와 class 를 이용하여 css에서 속성을 설정 할 수 있다

id를 이용할 때는 #

class를 이용할 때는 .

 

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      #header {
        width: 500px;
        background-color: #ffcc00;
        border: 1px solid #000000;
        text-align: center;
      }
      #wrap {
        width: 500px;
        background-color: #00ffdd;
        border: 2px solid #ea00ff;
        text-align: center;
        overflow: hidden;
      }
      #content {
        width: 350px;
        background-color: #ffcc00;
        border: 2px solid #000000;
        float: left;
      }
      #side_banner {
        background-color: #ffcc00;
        border: 2px solid #000000;
        float: left;
      }
      #footer {
        clear: both;
        width: 500px;
        background-color: #ff0080;
        border: 1px solid #66fa03;
        text-align: center;
      }
      .menu1 {
        color: #aaaaaa;
        font-weight: bold;
      }
      .menu1,
      .menu3,
      .menu5 {
        font-size: 20px;
      }
    </style>
  </head>
  <body>
    <div id="header">
      <h1>HEADER</h1>
    </div>

    <div id="wrap">
      <div id="content">
        <h1>CONTENT</h1>
        <ul>
          <li class="menu1">menu1</li>
          <li class="menu2">menu2</li>
          <li class="menu3">menu3</li>
          <li class="menu4">menu4</li>
          <li class="menu5">menu5</li>
        </ul>
      </div>
      <div id="side_banner">
        <h1>BANNER</h1>
        <a href="https://www.naver.com/"
          ><img
            width="100px"
            src="https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyMDEwMjRfMTU3%2FMDAxNjAzNDgyNTU0Mjg0.-Rc206zme2K6XKWJjosmHucpqDj8sqNvzhZeAVCwb08g.gFvmgVX1_N2-7SXYkzzhwDGxNoRzsRmHdGmPRFuMCW8g.GIF.boccabe%2Fnaver.gif&type=a340"
            alt="naver"
        /></a>
      </div>
    </div>
    <div id="footer">
      <h1>FOOTER</h1>
    </div>
  </body>
</html>

 

 

float를 할 때 overflow에 hidden을 해줘야한다.

 

text-align: 텍스트 정렬 방향

-left: 왼쪽 정렬

-center: 중앙 정렬

-right: 오른쪽 정렬

-justify: 양쪽 정렬(자동 줄바꿈시 오른쪽 경계선 부분 정리)

 

overflow: 요소의 콘텐츠가 너무 커서 요소의 블록 서식 맥락에 맞출 수 없을 때의 처리법

-visible: 넘친부분까지 보이기

-hidden: 넘친부분 숨기기

-scroll: 스크롤 형식

-auto: 사용자 에이전트가 결정

https://developer.mozilla.org/ko/docs/Web/CSS/overflow

 

overflow - CSS: Cascading Style Sheets | MDN

overflow CSS 단축 속성은 요소의 콘텐츠가 너무 커서 요소의 블록 서식 맥락에 맞출 수 없을 때의 처리법을 지정합니다. overflow-x, overflow-y의 값을 설정합니다. The source for this interactive example is stored

developer.mozilla.org

float: 한 요소(element)가 보통 흐름(normal flow)으로부터 빠져 텍스트 및 인라인(inline) 요소가 그 주위를 감싸는 자기 컨테이너 좌우측을 따라 배치되어야 함을 지정함, 한마디로 주위에 감싸는 걸 하는가 안하는가를 의미, 둥둥 떠 움직이는 것

-none: 요소가 부동하지 않아야함, 주위 둘러싸지 않음

-left: 요소가 자신의 포함(containing) 블록의 좌측에 부동(float, 떠움직여)해야 함을 나타냄

-right: 요소가 자신의 포함 블록의 우측에 부동해야 함을 나타냄

-inline-start: 요소가 자신의 포함 블록의 시작쪽에 부동해야 함을 나타냄

-inline-end: 요소가 자신의 포함 블록의 끝쪽에 부동해야 함을 나타냄. 즉 Itr 스크립트 상에서 오른쪽 그리고 rtl 스크립트 상에서는 왼쪽

https://developer.mozilla.org/ko/docs/Web/CSS/float

 

float - CSS: Cascading Style Sheets | MDN

CSS 속성(property) float 은 한 요소(element)가 보통 흐름(normal flow)으로부터 빠져 텍스트 및 인라인(inline) 요소가 그 주위를 감싸는 자기 컨테이너의 좌우측을 따라 배치되어야 함을 지정합니다. The so

developer.mozilla.org

clear: 요소가 선행 부동(floating) 요소 다음일 수 있는지 또는 그 아래로 내려가(해제되어(cleared))야 하는지를 지정

-none: 요소가 지난 부동 요소를 해제하기 위해 아래로 이동되지 않음을 나타내는 키워드

-left: 요소가 지난 left 부동체를 해제하기 위해 아래로 이동됨을 나타내는 키워드

-right: 요소가 지난 right 부동체를 해제하기 위해 아래로 이동됨을 나타내는 키워드

-both: 요소가 지난 both left 및 right 부동체를 해제하기 위해 아래로 이동됨을 나타내느 키워드

https://developer.mozilla.org/ko/docs/Web/CSS/clear

 

clear - CSS: Cascading Style Sheets | MDN

clear CSS 속성은 요소가 선행 부동(floating) 요소 다음일 수 있는지 또는 그 아래로 내려가(해제되어(cleared))야 하는 지를 지정합니다. clear 속성은 부동 및 비부동 요소 모두에 적용됩니다. The source f

developer.mozilla.org

tag, id, class 혼합

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      ul li.menu1 {
        color: #aaff00;
      }
      .menu2 {
        color: #00ffd5;
        font-weight: bold;
        font-size: 20px;
      }
      #menu {
        color: #eb0000;
      }
      #header {
        background-color: aqua;
        text-align: center;
        border: 2px solid #000000;
      }
      #wrap {
        background-color: #ffee00;
        border: 2px solid #000000;
        overflow: scroll;
      }
      #content1 {
        border: 1px;
        width: 250px;
        float: left;
      }
      #content2 {
        border: 1px;
        width: 250px;
        float: left;
      }
      #footer {
        background-color: aqua;
        clear: both;
        border: 2px solid #000000;
      }
      * {
        width: 500px;
      }
    </style>
  </head>
  <body>
    <div id="header">
      <h1>header</h1>
    </div>

    <div id="wrap">
      <div id="content1">
        <ul>
          <li id="menu">menu</li>
          <li class="menu1">menu</li>
          <li class="menu2">menu</li>
          <li class="menu1">menu</li>
          <li class="menu2">menu</li>
        </ul>
      </div>

      <div id="content2">
        <ol>
          <li class="menu1">menu</li>
          <li class="menu2">menu</li>
          <li class="menu1">menu</li>
          <li class="menu2">menu</li>
          <li class="menu1">menu</li>
        </ol>
      </div>
    </div>

    <div id="footer">
      <h1>footer</h1>
    </div>
  </body>
</html>

ul li .menu =>ul태그 안에 li태그 안에 menu를 선택

 

속성 선택자

tag의 속성을 선택하여 CSS의 속성을 설정 할 수 있다.

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      input {
        color: rgb(255, 140, 0);
        font-size: 30px;
        font-weight: bold;
      }
      input[type="text"] {
        color: #ff0000;
        font-size: 50px;
        width: 200px;
      }
      input[type="tel"] {
        color: blue;
      }
      img[src] {
        border: 5px solid green;
      }
    </style>
  </head>
  <body>
    <form>
      이름: <input type="text" /><br />
      아이디: <input type="text" /><br />
      비밀번호: <input type="password" /><br />
      전화번호: <input type="tel" /><br />
    </form>
    <img
      src="https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyMTAxMjFfMTkx%2FMDAxNjExMTU1MTYwNzY3.Ud-RGzNn46Vs9ftBU0gaXaH5vIFCHro8TA230qMMZX4g.st3kqQD_bzQo4WXblhUDNfKJI-fOdNCMpdL4rqrviXYg.PNG.djgkrrl1234%2Fimage.png&type=sc960_832"
      alt="네이버"
      width="100px"
    />
  </body>
</html>

 

[]를 이용해 속성 표시

 

 

후손 및 자손 선택자

tag의 속성을 선택하여 CSS의 속성을 설정 할 수 있다.

 

가족관계 식으로 할경우

 

자손 선택자: 바로 밑에 있는 태그 선택, >으로 구분

후손 선택: 밑에 있는 모든 것 선택, 공백으로 구분

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      #header,
      #wrap {
        border: 1px solid rgb(255, 0, 0);
      }
      /*후손*/
      div li {
        background-color: rgb(215, 176, 253);
      }
      div p {
        font-size: 5px;
      }
      /*자손*/
      div > h1 {
        font-weight: bold;
        color: yellow;
      }
    </style>
  </head>
  <body>
    <div id="header">
      <div class="logo">
        <h1>LOGO</h1>
        <!--여기부분이 div 자손이라 노란색으로 바뀐다-->
      </div>
      <div class="copy">
        <h2>global company</h2>
      </div>
    </div>

    <div id="wrap">
      <!--여기부분은 div 후손이라 글씨 사이즈가 5px로 바뀐다-->
      <p>제목</p>
      <ul>
        <!--여기부분은 div 후손이라 글씨 사이즈가 5px로 바뀐다-->
        <li><p>가가가</p></li>
        <!--여기부분은 div 후손이라 노란색으로 바뀌지 않는다-->
        <li><h1>나나나</h1></li>
        <!--여기부분은 div 후손이라 글씨 사이즈가 5px로 바뀐다-->
        <li><p>다다다</p></li>
        <!--여기부분은 div 후손이라 노란색으로 바뀌지 않는다-->
        <li><h1>라라라</h1></li>
      </ul>
    </div>
  </body>
</html>

 

div li => div 안에 li, 후손일 경우 공백으로 표시

div>h1 => div 안에 바로 h1을 선택

 

동위 선택자

태그의 동등한 위치를 판단하여 CSS속성을 설정 할 수 있다

 

+: 그 태그와 바로 근접해 있는 태그 하나 선택

~: 그 태그와 동등한 위치에 있는 태그들 중에 다 선택

 

더보기
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      h3 ~ div {
        font-size: 10px;
        color: orange;
      }
      h3 + div {
        font-size: 20px;
        font-weight: bold;
        color: orchid;
      }
      #title ~ div {
        width: 300px;
        background-color: yellow;
      }
    </style>
  </head>
  <body>
    <h3 id="title">동위 선택자(+,~)</h3>
    <!--h3+div에 의해 크기와 색깔이 바뀜-->
    <div>div_01</div>
    <!--h3~div에 의해 크기와 색깔이 바뀜-->
    <div>div_02</div>
    <div>div_03</div>
    <div>div_04</div>
    <div>div_05</div>
  </body>
</html>

 

반응형

'Web > css' 카테고리의 다른 글

CSS-(4)  (0) 2021.02.19
CSS-(3)  (0) 2021.02.19
CSS-(1)  (2) 2021.02.05

+ Recent posts